我终于研究了async和await关键字,我有点"得到",但我见过的所有例子都在.Net框架中调用异步方法,例如这个调用HttpClient.GetStringAsync()
.
我不太清楚的是这种方法会发生什么,以及我如何编写自己的"等待"方法.它是否像包装我想在Task中异步运行的代码并返回那样简单?
Jan*_*s F 78
这很简单
Task.Run(() => ExpensiveTask());
Run Code Online (Sandbox Code Playgroud)
为了使它成为一个等待的方法:
public Task ExpensiveTaskAsync()
{
return Task.Run(() => ExpensiveTask());
}
Run Code Online (Sandbox Code Playgroud)
这里重要的是返回一个任务.该方法甚至不必标记为异步.(只是进一步阅读它进入图片)
现在这可以称为
async public void DoStuff()
{
PrepareExpensiveTask();
await ExpensiveTaskAsync();
UseResultsOfExpensiveTask();
}
Run Code Online (Sandbox Code Playgroud)
注意,方法签名在这里说async
,因为该方法可以将控制返回给调用者直到ExpensiveTaskAsync()
返回.而且,在这种情况下昂贵意味着耗时,如网络请求或类似的.要将繁重的计算发送到另一个线程,通常最好使用"旧"方法,即System.ComponentModel.BackgroundWorker
用于GUI应用程序或System.Threading.Thread
.
svi*_*ick 13
我将如何编写自己的"等待"方法?它是否像包装我希望在a中异步运行
Task
并返回的代码一样简单?
这是一个选项,但它很可能不是您想要做的,因为它实际上并没有为您提供异步代码的许多优点.有关更多详细信息,请参阅Stephen Toub 应该为同步方法公开异步包装器吗?
一般来说,方法是不可取的,类型是.如果您希望能够编写类似的东西await MyMethod()
,则MyMethod()
必须返回Task
,Task<T>
或者自定义await
类型.使用自定义类型是一种罕见的高级方案; 使用Task
,你有几个选择:
async
和编写你的方法await
.这对于异步编写动作很有用,但它不能用于最内部的await
调用.Task
使用其中一种方法创建Task
,例如Task.Run()
或Task.FromAsync()
.TaskCompletionSource
.这是最通用的方法,它可以用于await
从将来发生的任何事情创建有效的方法.nos*_*tio 11
......我将如何编写自己的"等待"方法.
回归Task
不是唯一的方法.你可以选择创建一个自定义awaiter(通过实现GetAwaiter
和INotifyCompletion
),这是一个很好的阅读:"等待任何事情".返回自定义awaiters的.NET API示例:Task.Yield()
,Dispatcher.InvokeAsync
.
// don't use this in production
public static class SwitchContext
{
public static Awaiter Yield() { return new Awaiter(); }
public struct Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
public Awaiter GetAwaiter() { return this; }
public bool IsCompleted { get { return false; } }
public void OnCompleted(Action continuation)
{
ThreadPool.QueueUserWorkItem((state) => ((Action)state)(), continuation);
}
public void GetResult() { }
}
}
// ...
await SwitchContext.Yield();
Run Code Online (Sandbox Code Playgroud)
是的,从技术上讲,您只需要从方法中返回 aTask
或即可实现可等待的方法。Task<Result>
async
这支持基于任务的异步模式。
但是,有多种实施 TAP 的方法。有关详细信息,请参阅实现基于任务的异步模式。
(但所有这些实现仍然返回Task
or Task<Result>
,当然。)
只需将您的方法转换为任务。像@Romiox 一样,我通常使用这个扩展名:
public static partial class Ext
{
#region Public Methods
public static Task ToTask(Action action)
{
return Task.Run(action);
}
public static Task<T> ToTask<T>(Func<T> function)
{
return Task.Run(function);
}
public static async Task ToTaskAsync(Action action)
{
return await Task.Run(action);
}
public static async Task<T> ToTaskAsync<T>(Func<T> function)
{
return await Task.Run(function);
}
#endregion Public Methods
}
Run Code Online (Sandbox Code Playgroud)
现在让我们说你有
void foo1()...
void foo2(int i1)...
int foo3()...
int foo4(int i1)...
Run Code Online (Sandbox Code Playgroud)
...
然后你可以像@Romiox一样声明你的[async Method]
async Task foo1Async()
{
return await Ext.ToTask(() => foo1());
}
async Task foo2Async(int i1)
{
return await Ext.ToTask(() => foo2(i1));
}
async Task<int> foo3Async()
{
return await Ext.ToTask(() => foo3());
}
async Task<int> foo4Async(int i1)
{
return await Ext.ToTask(() => foo4(i1));
}
Run Code Online (Sandbox Code Playgroud)
或者
async Task foo1Async()
{
return await Ext.ToTaskAsync(() => foo1());
}
async Task foo2Async(int i1)
{
return await Ext.ToTaskAsync(() => foo2(i1));
}
async Task<int> foo3Async()
{
return await Ext.ToTaskAsync(() => foo3());
}
async Task<int> foo4Async(int i1)
{
return await Ext.ToTaskAsync(() => foo4(i1));
}
Run Code Online (Sandbox Code Playgroud)
...
现在您可以对任何 fooAsync 方法使用 async 和 await,例如 foo4Async
async Task<int> TestAsync () {
///Initial Code
int m = 3;
///Call the task
var X = foo4Async(m);
///Between
///Do something while waiting comes here
///..
var Result = await X;
///Final
///Some Code here
return Result;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38360 次 |
最近记录: |