【问题标题】:cannot await object in the async call无法在异步调用中等待对象
【发布时间】:2014-11-12 23:21:17
【问题描述】:

我有一个名为 DoSomething() 的方法,它返回一个 object 并且非常耗时。所以我想使用 async/await 让它在后台运行,而我的 GUI 显示“等待响应...”消息。

在我的调用方法中:

Task taskDoSomething = new Task(DoSomethingAsync);
taskDoSomething.Start();
taskDoSomething.Wait();
// continue the program

我的DoSomethingAsync 方法:

private async void DoSomethingAsync()
{
    Object result = await DoSomething();
}

但我得到了错误:

无法等待 [ObjectType]

[ObjectType] 是我自己创建的一种对象。我只是使用上面的对象,以免混淆读者。

请让我知道我做错了什么,让我摆脱BackgroundWorker的零散处理。

【问题讨论】:

    标签: c# winforms asynchronous async-await


    【解决方案1】:

    我认为您误解了 asyncawait 的工作原理。如果DoSomething() 是一个长期运行的方法,不是为异步设计的,你可能只想在不同的线程中执行它,例如通过开始一个单独的任务:

    Task<object> task = Task.Run<object>(DoSomething);
    

    请注意,这意味着 DoSomething 将无法与 UI 交互,因为它将位于不同的线程上。

    然后,如果您愿意,您可以await 该任务 - 但只能通过异步方法。如果不了解更多上下文,很难给出更具体的建议。

    从您的 cmets 中,您可能有以下内容:

    private async void HandleButtonClick(object sender, EventArgs e)
    {
        Task<object> task = Task.Run<object>(DoSomething);
        object result = await task;
        status.Text = "I've done something";
        // Use the result?
    }
    

    【讨论】:

    • 我想要的是与BackgroundWorker 类似的东西。当用户按下按钮时,应显示waiting for response 徽标,直到DoSomethin() 完成其工作,然后显示类似Job is Done! 的状态消息
    • @JonSkeet 你不是通过调用task.Result来阻止吗?
    • @I3arnon:嗯,是的 - 那应该是await task。不知道那里发生了什么...虽然已修复。
    • @JonSkeet 如果DoSomething 有参数怎么办?我正在使用您的解决方案,但收到 The best overloaded method match for ... has some invalid arguments 错误。
    • @Pedram:那么你会使用Task.Run(() =&gt; DoSomething(argument))。如果您的 example 使用了参数,那么我的答案也会:)
    【解决方案2】:

    如果DoSomething 是同步的(看起来是这样),并且您想将其卸载到不同的线程以保持 UI 响应,您应该使用 Task.Run

    async Task DoSomethingAsync()
    {
        var result = await Task.Run(() => DoSomething());
    }
    

    您也不应该使用async void,除非在事件处理程序中。
    没有理由直接创建任务。要么让DoSomethingAsync 返回Task,要么完全删除该方法并直接使用Task.Run


    如果 DoSomething 本质上是异步的,您应该使用 async-await 实现它并让它隐式返回一个任务。

    【讨论】:

    • 我从dotnetperls.com/async 学到了async void。当我将您的 async Task 更改为 async void 时它可以工作,但现在我想在 Task taskDoSomething = new Task(DoSomethingAsync); 之后使用的所有语句都并行运行。我想知道DoSomething() 什么时候完成它的工作,所以我决定对用户做什么。
    • @Pedram 这是一个不好的参考。你应该看看 Stephen Cleary 的介绍:blog.stephencleary.com/2012/02/async-and-await.html
    猜你喜欢
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多