2012-05-30 88 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