Updating UI from a different thread

2019-01-15 22:52发布

I know this question has been asked before, but I feel it wasn't asked correctly.

I have an intensive operation and I'd like the UI to remain responsive. I've read a few posts that say Background worker is the best way to go, however, I think this assumes you have the source code to the intensive task.

I have a library that I have no source code for, the only way I can check on the progress is to attach to events that get fired and get information that way.

The example I saw on the MSDN site assumed one would have the source.

I know how to get progress (which is a percentage value) by attaching to events, but how do I get that value back to the UI?

4条回答
来,给爷笑一个
2楼-- · 2019-01-15 23:08

You can have the desired effect by using a second thread and a thread safe queue.

You can create a second thread that will listen for the events. When a new event happens it pushes the event information to a queue (thread safe- synchronized).

Using a Timer (Windows.Forms.Timer) that will check that queue every x time and in case new events exist can update the UI.

Because the timer runs in the main thread it can safely update the UI and if you make it light weight it will not block it long enough to be noticed.

查看更多
Melony?
3楼-- · 2019-01-15 23:12

A similar discussion is on this Q. If you can't or don't want to use the BackgroundWorker for whatever reason you can use your own thread and marshal events from it back onto your UI thread.

private void Initialise() {      
    MyLibClass myLibClass = new MyLibClass();
    myLibClass.SomeEvent += SomeEventHandler;
    ThreadPool.QueueUserWorkItem(myLibClass.StartLongTask);
}


private void SomeEventHandler(EventArgs e) {     
   if (this.Dispatcher.Thread != Thread.CurrentThread) { 
      this.Dispatcher.Invoke(delegate { DoStuffOnUIThread(e); });
   }
   else {        
       DoStuffOnUIThread(e);     
   }
}
查看更多
时光不老,我们不散
4楼-- · 2019-01-15 23:14

Attach to the progress events in the third party component and call ReportProgress on the BackgroundWorker. Have your UI attach to the BackgroundWorker.ProgressChanged event to update the UI.

查看更多
5楼-- · 2019-01-15 23:19

The following answer is based on my gut feeling and have not actually done it a test with third party libs.

  • Call your third party lib code as usual you call in a simple background (not BackGroundWorker) thread.
  • Attach the library components' events to normal event handlers in your code (meant to update UI).
  • In the event handler code should look like this:

    private void EventHandler(object sender, DirtyEventArgs e)
    {
        if (myControl.InvokeRequired)
            myControl.Invoke(new MethodInvoker(MethodToUpdateUI), e);
        else
            MethodToUpdateUI(e);
    }
    
    private void MethodToUpdateUI(object obj) 
    {
        // Update UI
    }
    
查看更多
登录 后发表回答