2012-05-30 82 views
3

我有幾個需要在Windows窗體應用程序的後臺運行的過程,因爲它們需要太多時間,我不想凍結用戶界面,直到它們完全結束,我想要一個顯示每個操作過程的指示器,到目前爲止,我有一個表單來顯示每個操作的進度,但是我的操作同步運行。C#中的異步方法

所以我的問題是什麼是最簡單的方式來運行這些操作(即訪問數據庫)異步?

我忘了應用程序要求的一個重要功能,用戶可以隨時選擇取消任何操作。我認爲這個要求使應用程序複雜化很多,至少在我目前的技能方面,所以基本上我想讓我需要一個易於理解,易於實現的解決方案。我是知道會有好的做法遵循,但在這一點上,我想了一些代碼後工作,我有更多的時間我會重構代碼

回答

2

那麼在C#中有幾種方法可以做到這一點

我個人建議你嘗試無擴展

http://msdn.microsoft.com/en-us/data/gg577609.aspx

實際上,你可以做這樣的事情:

https://stackoverflow.com/a/10804404/1268570

我創造了這個給你,這是很容易的,雖然它不是線程安全的,但是這將是一個很好的起點

在形式

var a = Observable.Start(() => Thread.Sleep(8000)).StartAsync(CancellationToken.None); 
var b = Observable.Start(() => Thread.Sleep(15000)).StartAsync(CancellationToken.None); 
var c = Observable.Start(() => Thread.Sleep(3000)).StartAsync(CancellationToken.None); 

Manager.Add("a", a.ObserveOn(this).Subscribe(x => MessageBox.Show("a done"))); 
Manager.Add("b", b.ObserveOn(this).Subscribe(x => MessageBox.Show("b done"))); 
Manager.Add("c", c.ObserveOn(this).Subscribe(x => MessageBox.Show("c done"))); 

private void button1_Click(object sender, EventArgs e) 
{ 
    Manager.Cancel("b"); 
} 

管理器實用

public static class Manager 
{ 
    private static IDictionary<string, IDisposable> runningOperations; 

    static Manager() 
    { 
     runningOperations = new Dictionary<string, IDisposable>(); 
    } 

    public static void Add(string key, IDisposable runningOperation) 
    { 
     if (runningOperations.ContainsKey(key)) 
     { 
      throw new ArgumentOutOfRangeException("key"); 
     } 

     runningOperations.Add(key, runningOperation); 
    } 

    public static void Cancel(string key) 
    { 
     IDisposable value = null; 
     if (runningOperations.TryGetValue(key, out value)) 
     { 
      value.Dispose(); 
      runningOperations.Remove(key); 
     } 
    } 
2

如果ORM /數據庫API本身沒有附帶異步方法,請查看BackgroundWorker Class。它支持取消(CancelAsync/CancellationPending)和進度報告(ReportProgress/ProgressChanged)。

+1

BackgroundWorker可以工作,但是對於使用異步操作有一些巨大的缺點。處理多個任務比較困難(即:在所有任務完成時運行某些任務)。 –

+0

是的。另一方面,任務進度報告比BackgroundWorker更難。 – dtb

+0

我不同意 - 如果您從UI上下文中創建TaskScheduler,則報告可能更容易,因爲您不必將要報告的信息映射到傳遞給ReportProgress事件的信息。 「報告」只是安排另一項任務。 –

3

.NET 4增加了Task Parallel Library,它提供了一個非常乾淨的機制來使異步操作異步。

它允許您將同步操作包裝到任務中,然後您可以等待或使用延續(某些代碼在任務完成時執行)。

這往往會是這個樣子:

Task processTask = Task.Factory.StartNew(() => YourProcess(foo, bar)); 

一旦你的任務,你有好幾個選擇,其中包括阻止:

// Do other work, then: 
processTask.Wait(); // This blocks until the task is completed 

或者,如果你想有一個延續(代碼當它完成時運行):

processTask.ContinueWith(t => ProcessCompletionMethod()); 

你也可以用它來組合多個asynchrono我們的操作,並在任何或全部完成時完成,等等。

請注意,以這種方式使用TaskTask<T>還有一個巨大的優勢 - 如果以後遷移到.NET 4.5,你的API一樣工作是,沒有代碼的變化,與新的異步/等待語言功能在未來C#5.

我忘了應用程序需要的一個重要功能,用戶可以隨時取消任何操作。

的TPL也被設計,從它成立以來,以結合新cooperative cancellation model很好地工作於.NET 4這樣,你有哪些可用於取消任何或所有的任務CancellationTokenSource