循环中的WPF应用程序,如何不冻结整个应用程序?

时间:2009-03-16 19:39:38

标签: c# .net wpf multithreading

我正在玩WPF并遇到问题。我用Google搜索并发现这个website与我有同样的问题,但没有任何有效的解决方案。

问题是我有一个按钮可以处理一些数据(大约30秒)。我想让按钮禁用并在文本框中写日志...问题是它没有禁用,并且在处理完成之前它没有在文本框上写任何东西。

有什么想法吗?

 private void button1_Click(object sender, RoutedEventArgs e)
 {
        this.button1.IsEnabled = false;
        //Long stuff here
         txtLog.AppendText(Environment.NewLine + "Blabla");
        //End long stuff here
        this.button1.IsEnabled = true;
 }

3 个答案:

答案 0 :(得分:8)

正如其他人所说,使用BackgroundWorker或其他一些同步工作的方法。

您可以在Window下声明它,将其初始化为Loaded事件,并在Click事件中使用它。这是您的方法,已修改为使用BackgroundWorker,假设您已在Window下将其声明为_bw

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _bw = new BackgroundWorker();
    _bw.DoWork += new DoWorkEventHandler((o, args) =>
    {
        //Long stuff here       
        this.Dispatcher.Invoke((Action)(() => txtLog.AppendText(Environment.NewLine + "Blabla")));
    });

    _bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((o, args) =>
    {
        //End long stuff here
        this.Dispatcher.Invoke((Action)(() => this.button1.IsEnabled = true));
    });
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    this.button1.IsEnabled = false;

    _bw.RunWorkerAsync();
}

请注意,从其他线程修改UI的任何内容都必须在Dispatcher.InvokeDispatcher.BeginInvoke调用内完成,WPF不允许您从任何线程获取或设置DependencyProperty值但创建对象的那个(更多关于此here)。

如果您想阅读txtLog而不是修改它,代码将是相同的:

//Long stuff here       
this.Dispatcher.Invoke((Action)(() => 
{
    string myLogText = txtLog.Text;
    myLogText = myLogText + Environment.NewLine + "Blabla";
    txtLog.Text = myLogText;
}));

答案 1 :(得分:3)

做异步。创建一个后台工作流程来处理数据,应用程序将继续响应。 MSDN Resources on the Class。由于WPF使用C#(或VB.net),您仍然可以使用相同类型的线程对象。我自己在WPF应用程序中成功使用了后台工作程序。

答案 2 :(得分:3)

正在UI线程上执行该操作。这意味着它将阻止Windows消息泵处理直到它完成。没有泵=没有UI更新。您应该在另一个线程上启动该作业。我不知道WPF,但在C#中我会使用Thread或BackgroundWorker类。