技术开发 频道

跨线程操作GUI

.NET 3.0 WPF

Control.Invoke变成了Dispatcher.Invoke。内部实现还是一样的,有一个Callback队列,然后PostMessage。同时引入的还有DispatcherSynchronizationContext。

Conculsion

从直接PostMessage到Control.Invoke到SynchronizationContext到AsyncOperationManager到BackgroundWorker,职责最终推卸到了回调的提供方。但是由于引入的时间不一致,很多回调提供方是没有使用AsyncOperation的。这个时候,我们自己需要自己去包装,比如:

using System;
using System.ComponentModel;
using System.Net;
using log4net;

namespace xxx
{
    
public class WebClientFileUploader : FileUploaderListeners, FileUploader
    {
        
private static readonly ILog LOGGER = LogManager.GetLogger(typeof (WebClientFileUploader));
        
private readonly WebClient webClient;
        
private readonly Uri address;
        
private readonly AsyncOperation asyncOperation;

        
public WebClientFileUploader(Uri address)
        {
            asyncOperation
= AsyncOperationManager.CreateOperation(null);
            webClient
= new WebClient();
            webClient.UploadFileCompleted
+= HandleUploadFileCompleted;
            
this.address = address;
        }

        
private void HandleUploadFileCompleted(object sender, UploadFileCompletedEventArgs eventArgs)
        {
            
try
            {
                var result
= eventArgs.Result;
                LOGGER.Info(
"Request completed.");
                asyncOperation.Post(state
=> HandleCompleted(result), null);
            }
            
catch (Exception exception)
            {
                LOGGER.Error(
"Request failed.", exception);
                asyncOperation.Post(state
=> HandleError(exception), null);
            }
        }

        
public void Cancel()
        {
            LOGGER.Info(
"Cancelling the request.");
            webClient.CancelAsync();
        }

        
public void Upload(string fileName)
        {
            LOGGER.Info(
"Starting to upload to " + address + " with file " + fileName + " using real web client.");
            webClient.UploadFileAsync(address, WebRequestMethods.Http.Post, fileName);
        }
    }
}


这样,我们就不需要在手工地去用Control.Invoke了,也不应该再直接用Control.Invoke了。

0
相关文章