UI线程块

发布于 2024-12-06 01:45:53 字数 698 浏览 4 评论 0原文

我创建了一个简单的 WPF 应用程序,并向默认窗口添加了一个按钮。当我单击按钮时,会调用一个模拟的长工作方法(使用 Thread.Sleep(15000) 进行模拟)。我试图使按钮异步执行,但是尽管遵循在线示例,按钮和整个窗口都会在我锁定时锁定单击并保持如此状态,直到 Thread.Sleep(...) 完成。

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

以下是代码:

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();
}

I have created a simple WPF Application and added a button to the default window. When I click on the button, a simulated long working method(simulated using a Thread.Sleep(15000) is called. I am trying to make the button execute asynchronously however despite following online examples, the button and entire window locks as soon as I click and remains so until the Thread.Sleep(...) finishes.

Any ideas why this is happening?

Here is the code:

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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

毁梦 2024-12-13 01:45:54

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

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);
                })); 
      } 
    )); 

所以,你应该像这样修改你的例子:

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类更容易。这是一个例子:

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
}

You are putting the long operation back into the UI thread. Let me comment your example:

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);
                })); 
      } 
    )); 

So, you should modify your example like this:

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
                })); 
      } 
    )); 

As others have mentioned, it's easier to use the BackgroundWorker class. Here's an example:

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
}
自此以后,行同陌路 2024-12-13 01:45:54

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

仅当您从后台工作线程更新 UI 时才需要使用此选项。如果你只是:

 Thread thread = new System.Threading.Thread(
     new System.Threading.ThreadStart(
      delegate()
      {
           Thread.Sleep(15000);
      }
    ));

我认为它会起作用。

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

By using BeginInvoke you are actually executing the code on the UI thread.

You only need to use this when you are updating your UI from the background worker thread. If you simply have:

 Thread thread = new System.Threading.Thread(
     new System.Threading.ThreadStart(
      delegate()
      {
           Thread.Sleep(15000);
      }
    ));

I think it will work.

However, you aren't raising a "Work Completed" event so you have no way of knowing when (or indeed if) the thread has finished. Look into the BackgroundWorker class. This does a lot of the heavy lifting for you. You just need to plug in your code to the DoWork method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文