WPF 利用子线程弹出子窗体的研究

时间:2023-03-08 21:30:37
WPF 利用子线程弹出子窗体的研究

  一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了。稍后我会上传我的代码,包含测试程序以及之前两边博文谈到的控件,这里我还实现了一个类似雷达扫描的等待窗体,大家可以稍后查看。

  实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问UI界面。为了方便调用,我在这里写了一个静态的子线程窗体管理类DialogWindowsManager。

1.遮挡主窗体

  大家都知道,showDialog方法就是最好的遮挡效果,但是由于它是线程阻塞的,因此每当我们想到这里的时候会有一个误区,认为调用showDialog一定会阻塞前台界面,其实这里的阻塞只是阻塞调用方法所在的线程,并不是一定会阻塞主线程,因此在子线程中调用showDialog方法即可达到效果。实际测试时发现遮挡效果确实有了,可惜每次showDialog的时候窗体会满屏幕乱飞,好吧,最好的方法当然是设置onwer,不过我一直没尝试成功,因为主窗体与子窗体一直处于两个线程中,最后我通过一个算法将位置计算出来之后赋值给了子窗体。代码如下:

 /// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
}

2.跨线程访问

  这里不得不说WPF还是很给力的,因为它提供了Dispatcher来获取当前要更新的线程,这里网上资料很多,我就不多做解释了,直接上代码:

 /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
}

3.注意事项

  子线程也是UI线程,因此线程一定要设置为ApartmentState.STA状态。

完成的线程管理代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows; namespace MyUserControlLibrary
{
public static class DialogWindowsManager
{
#region 属性 /// <summary>
/// 等待窗体处理线程
/// </summary>
static Thread WaitingFormThread;
/// <summary>
/// 进度条进程
/// </summary>
static Thread CircleProgressFormThread; /// <summary>
/// 等待进度条进程
/// </summary>
static Thread WaitingAndProgressFormThread; /// <summary>
/// 进度条窗体
/// </summary>
static CircleProgressForm cf;
/// <summary>
/// 等待进度条
/// </summary>
static WaitingAndProgressForm wpf;
#endregion #region 私有方法 /// <summary>
/// 打开等待窗体方法
/// </summary>
private static void showWaitingForm(object o)
{
double[] d = (double[])o;
WaitingForm wf = new WaitingForm();
wf.WindowStartupLocation = WindowStartupLocation.Manual;
wf.Top = d[];
wf.Left = d[];
wf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showCircleProgressForm(object o)
{
double[] d = (double[])o;
cf = new CircleProgressForm();
cf.WindowStartupLocation = WindowStartupLocation.Manual;
cf.Top = d[];
cf.Left = d[];
cf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showWaitingAndProgressForm(object o)
{
object[] m = (object[])o;
double[] d = (double[])m[];
wpf = new WaitingAndProgressForm();
wpf.MainControl.ShowType = (WaitAndProgressType)m[];
wpf.WindowStartupLocation = WindowStartupLocation.Manual;
wpf.Top = d[];
wpf.Left = d[];
wpf.ShowDialog();
} #endregion #region 公有方法 /// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
} /// <summary>
/// 关闭等待窗体线程
/// </summary>
public static void CloseWaitingForm()
{
WaitingFormThread.Abort();
WaitingFormThread.Join();
WaitingFormThread.DisableComObjectEagerCleanup();
WaitingFormThread = null;
} /// <summary>
/// 打开进度条窗体线程
/// </summary>
public static void ShowCircleProgressForm(Window onwer)
{
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (CircleProgressFormThread == null)
{
CircleProgressFormThread = new Thread(new ParameterizedThreadStart(showCircleProgressForm));
CircleProgressFormThread.SetApartmentState(ApartmentState.STA);
CircleProgressFormThread.Start(d);
Thread.Sleep();
}
else
{
CloseCircleProgressForm();
ShowCircleProgressForm(onwer);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭进度条窗体线程
/// </summary>
public static void CloseCircleProgressForm()
{
CircleProgressFormThread.Abort();
CircleProgressFormThread.Join();
CircleProgressFormThread.DisableComObjectEagerCleanup();
CircleProgressFormThread = null;
cf = null;
} /// <summary>
/// 打开等待进度条窗体线程
/// </summary>
public static void ShowWaitingAndProgressForm(Window onwer,WaitAndProgressType t)
{
object[] o = new object[];
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
o[] = d;
o[] = t;
if (WaitingAndProgressFormThread == null)
{
WaitingAndProgressFormThread = new Thread(new ParameterizedThreadStart(showWaitingAndProgressForm));
WaitingAndProgressFormThread.SetApartmentState(ApartmentState.STA);
WaitingAndProgressFormThread.Start(o);
Thread.Sleep();
}
else
{
CloseWaitingAndProgressForm();
ShowWaitingAndProgressForm(onwer,t);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setWaitingAndProgressFormPercent(double d)
{
if (wpf != null)
{
wpf.Dispatcher.BeginInvoke(new Action(() => { if (wpf != null) { wpf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭等待进度条窗体线程
/// </summary>
public static void CloseWaitingAndProgressForm()
{
WaitingAndProgressFormThread.Abort();
WaitingAndProgressFormThread.Join();
WaitingAndProgressFormThread.DisableComObjectEagerCleanup();
WaitingAndProgressFormThread = null;
wpf = null;
} #endregion
}
}

整个解决方案我会上传的!!

如果喜欢我的文章可以粉我!!!

本文系本人原创,源代码及文章引用转载请注明出处!!谢谢!

源码下载地址:http://files.cnblogs.com/files/lgmbk/UserControlTest.zip