我终于研究了async和await关键字,我有点"得到",但我见过的所有例子都在.Net框架中调用异步方法,例如这个调用HttpClient.GetStringAsync().
我不太清楚的是这种方法会发生什么,以及我如何编写自己的"等待"方法.它是否像包装我想在Task中异步运行的代码并返回那样简单?
Jan*_*s F 78
这很简单
Task.Run(() => ExpensiveTask());
为了使它成为一个等待的方法:
public Task ExpensiveTaskAsync()
{
    return Task.Run(() => ExpensiveTask());
}
这里重要的是返回一个任务.该方法甚至不必标记为异步.(只是进一步阅读它进入图片)
现在这可以称为
async public void DoStuff()
{
    PrepareExpensiveTask();
    await ExpensiveTaskAsync();
    UseResultsOfExpensiveTask();
}
注意,方法签名在这里说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();
是的,从技术上讲,您只需要从方法中返回 aTask或即可实现可等待的方法。Task<Result>async
这支持基于任务的异步模式。
但是,有多种实施 TAP 的方法。有关详细信息,请参阅实现基于任务的异步模式。
(但所有这些实现仍然返回Taskor 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
}
现在让我们说你有
void foo1()...
void foo2(int i1)...
int foo3()...
int foo4(int i1)...
...
然后你可以像@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));
}
或者
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));
}
...
现在您可以对任何 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;
}
| 归档时间: | 
 | 
| 查看次数: | 38360 次 | 
| 最近记录: |