从async Task
调用通用回调的推荐方法是什么?例如,进度,异常处理和完成(但可能是其他状态)。
以下代码显示了实现它的一种方法,但感觉应该有一种更清晰的方法来处理它。 (FWIW我已经看到很多使用ContinueWith
作为完成回调的例子,但这并不真正处理其他情况,如进度和异常处理。)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Testcode
{
class TestApp
{
public static void Main()
{
AsyncCallbackTest test = new AsyncCallbackTest();
test.RunTest();
}
}
interface ICallback
{
void onProgress(String status);
void onCompleted();
void onFaulted(Exception e);
}
class AsyncCallbackTest : ICallback
{
public void RunTest()
{
//run task in background
Task task = new Task(new Action<Object>(ExampleTask), this);
task.Start();
//do something else here
//...
//wait for task completion
task.Wait();
}
public void onProgress(string status)
{
Console.Out.WriteLine(status);
}
public void onCompleted()
{
Console.Out.WriteLine("COMPLETED");
}
public void onFaulted(Exception e)
{
Console.Out.WriteLine("EXCEPTION: " + e.Message);
}
private void ExampleTask(object ocb)
{
ICallback callback = ocb as ICallback;
//do some work
try
{
DoSomething(callback);
}
catch (Exception e)
{
//how to pass exceptions/errors?
callback.onFaulted(e);
}
}
//example long-running task
private void DoSomething(ICallback callback)
{
callback.onProgress("Starting");
Thread.Sleep(5000);
callback.onProgress("Step 1 complete");
Thread.Sleep(5000);
callback.onProgress("Step 2 complete");
Thread.Sleep(5000);
callback.onCompleted();
}
}
}
答案 0 :(得分:4)
async
- await
非常容易完成和处理异常。进度处理正是IProgress
接口的用途。
因此,您的方法的签名将类似于:
public Task DoSomething(IProgress<string> progress = null);
你会这样称呼它:
try
{
await DoSomething(new Progress<string>(status => Console.WriteLine(status)));
Console.WriteLine("COMPLETED");
}
catch (Exception e)
{
Console.WriteLine("EXCEPTION: " + e.Message);
}
如果你不能使用C#5.0,那么你可以使用ContinueWith()
代替await
而你必须自己编写IProgress
和Progress
:
DoSomething(new Progress<string>(status => Console.WriteLine(status)))
.ContinueWith(t =>
{
if (t.Exception != null)
Console.WriteLine("EXCEPTION: " + t.Exception.InnerException.Message);
else
Console.WriteLine("COMPLETED");
});
答案 1 :(得分:3)
您可以使用IProgress<T>
界面或其Progress<T>
implementation。您可以找到描述其用法here的博客文章,但它基本上就像使用回调一样。
使用类似@Kirill Shlenskiy的Reactive Extensions也可以选择,但我认为使用Tasks添加对现有方法的支持可能不是最简单的解决方案。