栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

“ await Task.Run();”之间的任何区别 返回;” 和“返回Task.Run()”?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

“ await Task.Run();”之间的任何区别 返回;” 和“返回Task.Run()”?

主要区别在于 异常传播。 一个例外,内抛出

async Task
方法,获取存储在返回的
Task
对象和直到任务被通过观察保持hibernate
awaittask
task.Wait()
task.Result
task.GetAwaiter().GetResult()
。即使从方法的 同步
部分抛出,也以这种方式传播
async

考虑以下代码,其中

OneTestAsync
和的
AnotherTestAsync
行为完全不同:

static async Task oneTestAsync(int n){    await Task.Delay(n);}static Task AnotherTestAsync(int n){    return Task.Delay(n);}// call DoTestAsync with either oneTestAsync or AnotherTestAsync as whatTeststatic void DoTestAsync(Func<int, Task> whatTest, int n){    Task task = null;    try    {        // start the task        task = whatTest(n);        // do some other stuff,         // while the task is pending        Console.Write("Press enter to continue");        Console.ReadLine();        task.Wait();    }    catch (Exception ex)    {        Console.Write("Error: " + ex.Message);    }}

如果调用

DoTestAsync(OneTestAsync, -2)
,它将产生以下输出:

按Enter继续错误:发生一个或多个错误。等待Task.Delay错误:第二

注意,我必须按一下

Enter
才能看到它。

现在,如果我调用

DoTestAsync(AnotherTestAsync,-2)
,内部的代码工作流程
DoTestAsync
将大不相同,输出也将有所不同。这次,我没有被要求按
Enter

错误:该值必须为-1(表示无限超时),0或正整数。参数名称:millisecondsDelayError:1st

在这两种情况下

Task.Delay(-2)
,在验证其参数时都在开始时抛出。这可能是虚构的情况,但理论上
Task.Delay(1000)
也可能会抛出异常,例如,当基础系统计时器API发生故障时。

在一个侧面说明,误差传播逻辑为尚未不同

async void
的方法(而不是
asyncTask
方法)。如果当前线程有一个(。,它将
asyncvoid
通过
SynchronizationContext.Post
)重新抛出方法内部引发的异常(通过)立即在当前线程的同步上下文
SynchronizationContext.Current!= null)
中重新抛出
ThreadPool.QueueUserWorkItem
。调用者没有机会在同一堆栈帧上处理此异常。

我在这里和这里发布了有关TPL异常处理行为的更多详细信息。


:是否可以模仿基于

async
非异步
Task
方法的方法的异常传播行为,以使后者不会抛出相同的堆栈帧?

:如果确实需要,那么可以,有一个技巧:

// asyncasync Task<int> MethodAsync(int arg){    if (arg < 0)        throw new ArgumentException("arg");    // ...    return 42 + arg;}// non-asyncTask<int> MethodAsync(int arg){    var task = new Task<int>(() =>     {        if (arg < 0) throw new ArgumentException("arg");        // ...        return 42 + arg;    });    task.RunSynchronously(TaskScheduler.Default);    return task;}

但是请注意,在某些情况下(例如当堆栈太深时),

RunSynchronously
仍可以异步执行。


另一个显着区别是,

async
/
await
版本更容易出现死锁定在一个非默认的同步上下文
。例如,以下内容将在WinForms或WPF应用程序中死锁:

static async Task TestAsync(){    await Task.Delay(1000);}void Form_Load(object sender, EventArgs e){    TestAsync().Wait(); // dead-lock here}

将其更改为非异步版本,不会死锁:

Task TestAsync() {    return Task.Delay(1000);}

斯蒂芬·克莱里(Stephen Cleary)在他的博客中很好地解释了这种僵局。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/386422.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号