在 .net 4.0 中用 task.continuewith 模拟 async/await
Simulate async/await with task.continuewith in .net 4.0
是否可以在 .NET 4.0 中模拟 async/await 的行为而不使用 Microsoft.Bcl.Async
包?
我试过了运行
Task myTask = Task.Factory.Startnew(MyMethod,...)
myTask.ContinueWith((x)=>{
//do stuff when myTask is completed
},...);
//code that i hoped would run without waiting for myTask
但这会阻止我的 UI 而 myTask 是 运行。在搜索此问题时,我发现 this question 似乎问的是完全相同的问题,甚至还提供了带有完整代码示例的解决方案。但是,当我尝试调用 GetResponseWithRetryAsync
(或使用 task.Start()
调用 运行,或将其包装在 Task.Factory.StartNew()
中)时,它仍然阻塞我的 UI 线程。为什么 运行 的所有这些方式都阻碍了我的 UI?
编辑:根据用户 1
的请求阻止我的 UI 的示例代码
Task myTask = Task.Factory.StartNew(MyMethod, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
myTask.ContinueWith((x) =>
{
this.Title="Done!";
}, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
其中 MyMethod
是
public void MyMethod(){
WebRequest request = WebRequest.Create("http://google.com/");
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
reader.Close();
response.Close();
}
可以在没有编译器和框架帮助的情况下模仿 async-await
,尽管很难做到正确。您需要注意捕获上下文、异常处理、返回结果等。
您提到的情况不应在整个异步操作期间阻塞 UI。然而,在异步操作(如 DNS 解析)之前可能会进行一些同步工作。如果是这种情况,请使用 Task.Run
并将该工作卸载到 ThreadPool
线程以提高响应能力。
Task myTask = Task.Factory.Startnew(MyMethod)
myTask.ContinueWith((x)=>
{
//do stuff when myTask is completed
},new CancellationToken(),TaskContinuationOptions.OnlyOnRanToCompletion,TaskScheduler.FromCurrentSynchronizationContext());
这意味着继续不会阻塞您的 UI 线程。这里最主要的是TaskScheduler.FromCurrentSynchronisationContext()
是否可以在 .NET 4.0 中模拟 async/await 的行为而不使用 Microsoft.Bcl.Async
包?
我试过了运行
Task myTask = Task.Factory.Startnew(MyMethod,...)
myTask.ContinueWith((x)=>{
//do stuff when myTask is completed
},...);
//code that i hoped would run without waiting for myTask
但这会阻止我的 UI 而 myTask 是 运行。在搜索此问题时,我发现 this question 似乎问的是完全相同的问题,甚至还提供了带有完整代码示例的解决方案。但是,当我尝试调用 GetResponseWithRetryAsync
(或使用 task.Start()
调用 运行,或将其包装在 Task.Factory.StartNew()
中)时,它仍然阻塞我的 UI 线程。为什么 运行 的所有这些方式都阻碍了我的 UI?
编辑:根据用户 1
的请求阻止我的 UI 的示例代码Task myTask = Task.Factory.StartNew(MyMethod, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
myTask.ContinueWith((x) =>
{
this.Title="Done!";
}, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
其中 MyMethod
是
public void MyMethod(){
WebRequest request = WebRequest.Create("http://google.com/");
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
reader.Close();
response.Close();
}
可以在没有编译器和框架帮助的情况下模仿 async-await
,尽管很难做到正确。您需要注意捕获上下文、异常处理、返回结果等。
您提到的情况不应在整个异步操作期间阻塞 UI。然而,在异步操作(如 DNS 解析)之前可能会进行一些同步工作。如果是这种情况,请使用 Task.Run
并将该工作卸载到 ThreadPool
线程以提高响应能力。
Task myTask = Task.Factory.Startnew(MyMethod)
myTask.ContinueWith((x)=>
{
//do stuff when myTask is completed
},new CancellationToken(),TaskContinuationOptions.OnlyOnRanToCompletion,TaskScheduler.FromCurrentSynchronizationContext());
这意味着继续不会阻塞您的 UI 线程。这里最主要的是TaskScheduler.FromCurrentSynchronisationContext()