关于WPF的object被别的线程占有问题。

小馬 2011-06-09 10:11:37
情况是这样的有两个画面,form1和form2
在form1里面可以调用form2,
在form1里面
private form2 _operWin = new form2();

在form2的构造函数里面加了一个filewatch监视,
如果有文件生成就会调用File_Created方法。
private void File_Created(object source, FileSystemEventArgs e)
{
form2.backdisplay.Visibility = System.Windows.Visibility.Visible;
}

程序启动的时候form1会表示出来,然后往filewatch监视的文件夹里面拷贝一个文件,
这是就会调用File_Created方法,但是执行里面的那条语句的时候就出现错误了。
错误内容大概是这个意思,[backdisplay被别的线程占有了]。

有哪位知道怎么解决这个问题呢。
第一次接触WPF,请大家给指点指点。



案:
private void File_Created(object source, FileSystemEventArgs e)
{
new Thread(() =>
{
this.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => isVisiable()));
}).Start();
}

private void isVisiable()
{
form2.backdisplay.Visibility = System.Windows.Visibility.Visible;
}




在 WinForms 中,有时要执行耗时的操作,在该操作未完成之前操作用户界面,会导致用户界面停止响应。
解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作。
新建线程可以用 Thread 类,可以实现多线程同时操作,简单的可以通过 BackgroundWorker 类实现。
用 BackgroundWorker 类执行耗时的操作
BackgroundWorker 类在 System.ComponentModel 命名空间下。

常用方法
1.RunWorkerAsync
开始执行后台操作。引发 DoWork 事件

2.CancelAsync
请求取消挂起的后台操作。
注意:这个方法是将 CancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查 CancellationPending 属性,来决定是否要继续执行耗时的操作。


3.ReportProgress
引发 ProgressChanged 事件。


常用属性
1.CancellationPending
指示应用程序是否已请求取消后台操作。
只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。

2.WorkerSupportsCancellation
指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。

3.WorkerReportsProgress
指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。



常用事件
1.DoWork
调用 RunWorkerAsync 方法时发生。

2.RunWorkerCompleted
后台操作已完成、被取消或引发异常时发生。

3.ProgressChanged
调用 ReportProgress 方法时发生。



private BackgroundWorker backgroundWorker = new BackgroundWorker();

private void button1_Click(object sender, EventArgs e)
{
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.WorkerSupportsCancellation = true;

// 绑定执行的后台操作
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);

// 绑定后台操作完成后执行的方法
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

// 控制进度的方法
backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);

// 引发 DoWork 事件,这时就是在线程中执行 backgroundWorker_DoWork 方法
backgroundWorker.RunWorkerAsync();

button1.Enabled = false;
}

private void button2_Click(object sender, EventArgs e)
{
backgroundWorker.CancelAsync(); // 请求取消挂起的后台操作
}

// 这里不可以访问用户界面上的控件
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(5000);

// 报告进度,引发 ProgressChanged 事件
backgroundWorker.ReportProgress(50); // 这里完成了50%

if (!backgroundWorker.CancellationPending) // 判断用户是否执行了 CancelAsync 方法
{
System.Threading.Thread.Sleep(5000);
}
else
{
MessageBox.Show("中止了。");
}
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 这里可以访问用户界面上的控件
button1.Enabled = true;
}

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// 一般通过 ProgressBar 类来显示进度
MessageBox.Show(e.ProgressPercentage.ToString());

// e.ProgressPercentage、e.UserState
}

在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
如果想在 DoWork 事件处理程序中和用户界面的控件通信,可在用 ReportProgress 方法。
ReportProgress(int percentProgress, object userState),可以传递一个对象。
ProgressChanged 事件可以从参数 ProgressChangedEventArgs 类的 UserState 属性得到这个信息对象。

简单的程序用 BackgroundWorker 比 Thread 方便,Thread 中和用户界面上的控件通信比较麻烦,需要用委托来调用控件的 Invoke 或 BeginInvoke 方法,没有 BackgroundWorker 方便。
...全文
75 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
小馬 2011-06-09
  • 打赏
  • 举报
回复
up~~~~~~~~~~~~~~~~~~~
小馬 2011-06-09
  • 打赏
  • 举报
回复
up~~~~~~~~~~~~~~~~~~
小馬 2011-06-09
  • 打赏
  • 举报
回复
up~~~~~~~~~~~~~~~~

1,978

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 其他语言讨论
社区管理员
  • 其他语言社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧