首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

UI线程块
EN

Stack Overflow用户
提问于 2011-09-23 19:44:21
回答 3查看 10.6K关注 0票数 9

我已经创建了一个简单的WPF应用程序,并在默认窗口中添加了一个按钮。当我单击该按钮时,将调用一个模拟的long工作方法(使用Thread.Sleep(15000)模拟)。我试图让按钮异步执行,然而,尽管有下面的在线示例,按钮和整个窗口在我一单击时就会锁定,并一直保持到Thread.Sleep(...)完成。

你知道为什么会发生这种情况吗?

代码如下:

代码语言:javascript
运行
复制
private void button1_Click(object sender, RoutedEventArgs e)
{
   DoSomeAsyncWork();
}

private void DoSomeAsyncWork()
{
     System.Windows.Threading.Dispatcher.Run();
     Thread thread = new System.Threading.Thread(
         new System.Threading.ThreadStart(
          delegate()
          {
               Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Thread.Sleep(15000)));
          }
        ));
     thread.Start();
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-23 19:54:38

您正在将长操作放回到UI线程中。让我评论一下你的例子:

代码语言:javascript
运行
复制
Thread thread = new System.Threading.Thread( 
    new System.Threading.ThreadStart( 
        delegate() { 
            // here we are in the background thread

            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                new Action(() => {
                    // here we are back in the UI thread
                    Thread.Sleep(15000);
                })); 
      } 
    )); 

因此,您应该像这样修改您的示例:

代码语言:javascript
运行
复制
Thread thread = new System.Threading.Thread( 
    new System.Threading.ThreadStart( 
        delegate() { 
            // here we are in the background thread

            Thread.Sleep(15000);  // <-- do the long operation here

            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                new Action(() => {
                    // here we are back in the UI thread

                    // do stuff here that needs to update the UI after the operation finished
                })); 
      } 
    )); 

正如其他人所提到的,使用BackgroundWorker类更容易。下面是一个例子:

代码语言:javascript
运行
复制
private void DoSomeAsyncWork()   
{   
    BackgroundWorker bw = new BackgroundWorker();

    bw.DoWork += (sender, args) => {
        // do your lengthy stuff here -- this will happen in a separate thread
        Thread.Sleep(15000);
    }

    bw.RunWorkerCompleted += (sender, args) => {
        if (args.Error != null)  // if an exception occurred during DoWork,
            MessageBox.Show(args.Error.ToString());  // do your error handling here

        // do any UI stuff after the long operation here
        ...
    }

    bw.RunWorkerAsync(); // start the background worker
}
票数 16
EN

Stack Overflow用户

发布于 2011-09-23 19:51:51

通过使用BeginInvoke,您实际上是在UI线程上执行代码。

只有在从后台工作线程更新UI时,才需要使用它。如果你只是有:

代码语言:javascript
运行
复制
 Thread thread = new System.Threading.Thread(
     new System.Threading.ThreadStart(
      delegate()
      {
           Thread.Sleep(15000);
      }
    ));

我想它会起作用的。

但是,您不会引发“工作已完成”事件,因此您无法知道线程何时(或者是否)结束。查看BackgroundWorker class。这为您做了很多繁重的工作。您只需要将代码插入到DoWork方法中。

票数 4
EN

Stack Overflow用户

发布于 2011-09-23 19:51:05

您应该使用BackgroundWorker.

  • http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
  • http://www.tanguay.info/web/index.php?pg=codeExamples&id=232
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7528437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档