Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 立即执行一个任务,用于调用';它是在一个连续的街区内建造的吗?_C#_.net_Task - Fatal编程技术网

C# 立即执行一个任务,用于调用';它是在一个连续的街区内建造的吗?

C# 立即执行一个任务,用于调用';它是在一个连续的街区内建造的吗?,c#,.net,task,C#,.net,Task,首先,为标题道歉;我真的想不出如何简明扼要地表达我要做的事情 我有以下两项职能: 主代码: private async Task<PreparationInfo> PrepareRoundtrip() { PreparationInfo output = new PreparationInfo(); Task.Delay(3000); // stands in for a call to the server to fetch data for how to pre

首先,为标题道歉;我真的想不出如何简明扼要地表达我要做的事情

我有以下两项职能:

主代码:

private async Task<PreparationInfo> PrepareRoundtrip()
{
    PreparationInfo output = new PreparationInfo();

    Task.Delay(3000); // stands in for a call to the server to fetch data for how to prepare

    prepare(output) // package result into output

    return output;
}

private Task ExecuteWithPrepare()
{
    if (!PrepareEnabled) // instance variable
        return stateObject.Execute();
    else
    {
        Task<PreparationInfo> prepareTask = PrepareRoundtrip();
        return tceTask.ContinueWith((prepareTaskInternal) =>
        {
            stateObject.Execute(); // this is the Task that I need to return
        });
    }
}
internal Task Execute()
{
    ...
}
我正在为
stateObject.Execute()
方法编写一个包装器,它可以选择在执行之前调用一个准备方法(
PrepareRoundtrip()
),以处理一些参数

如果未启用准备(
PrepareEnabled==false
),我可以调用
Execute()
方向并立即返回它返回的任务。如果启用了准备,我需要运行准备方法(这是此任务特有的,我可以在必要时对其进行更改),然后运行
Execute()

我被困的部分是:

整个函数需要像直接调用
stateObject.Execute()
一样运行和返回,只是添加了
PrepareRoundtrip()
部分,这意味着两件事:

  • ExecuteWithPrepare()
    返回的任务需要表示
    stateObject.Execute()
    返回的任务

  • ExecuteWithPrepare()
    需要立即返回(即不要等待
    PrepareRoundtrip()

  • 实现这一目标的最佳方式是什么?谢谢

    TL;DR:

    private async Task<PreparationInfo> PrepareRoundtrip()
    {
        PreparationInfo output = new PreparationInfo();
    
        Task.Delay(3000); // stands in for a call to the server to fetch data for how to prepare
    
        prepare(output) // package result into output
    
        return output;
    }
    
    private Task ExecuteWithPrepare()
    {
        if (!PrepareEnabled) // instance variable
            return stateObject.Execute();
        else
        {
            Task<PreparationInfo> prepareTask = PrepareRoundtrip();
            return tceTask.ContinueWith((prepareTaskInternal) =>
            {
                stateObject.Execute(); // this is the Task that I need to return
            });
        }
    }
    
    internal Task Execute()
    {
        ...
    }
    
    stateObject.Execute()
    添加包装,以添加可能很长的额外准备步骤;需要立即返回表示原始结果的任务,而不是等待准备步骤首先完成

  • 使用
    展开
    任务
    (即您所拥有的)转换为
    任务
    ,表示内部
    任务
    的完成,而无需同步等待外部任务完成

  • 如果使用
    async
    方法,只需等待
    任务两次,而不是一次


  • 你根本不应该使用
    ContinueWith
    。这是一种过时的方法,行为很危险(特别是,它将使用当前的任务计划程序)

    相反,只需使用
    wait

    private Task ExecuteWithPrepareAsync()
    {
      if (!PrepareEnabled)
        return stateObject.ExecuteAsync();
      else
        return PrepareAndExecuteAsync();
    }
    
    private async Task PrepareAndExecuteAsync()
    {
      await PrepareRoundtripAsync();
      await stateObject.ExecuteAsync();
    }
    

    还要注意
    Async
    命名约定。

    示例代码中从不等待
    Task.Delay(3000);
    stateObject.Execute()
    虽然返回了一个任务,但它并不是一个异步方法;它是否仍应命名为
    ExecuteAsync
    ?它是在异步等待出现之前编写的。我真的希望我可以重写整个堆栈,以正确地使用async await,而不是这个过时的、低级的任务结构…@Benjin:如果它与
    await
    兼容,那么它应该被命名为
    ExecuteAsync
    。我对此进行了更深入的解释。问题在于代码的使用方式:对于大多数代码,
    ContinueWith
    -样式代码将在线程池或UI任务调度程序上运行-但是
    wait
    -样式代码将在线程池或UI同步上下文上运行。
    wait
    是因为它优先于TaskScheduler捕获SynchronizationContext。@Benjin如果该方法返回一个
    任务
    ,那么它是异步的,并且
    异步
    后缀是合适的。它如何使自己异步(无论是否使用
    等待
    )该方法的实现细节与其调用方无关。