簡體   English   中英

擴展 C# 異步/等待等待不等待

[英]Extending C# async/await await doesn't await

擴展: C# async/await await 不等待

如果順序執行的方法也存儲在列表中,我如何將ExecuteParallelAsync添加到該列表中?

private async Task ExecuteSequential()
{
    List<Action> sequentialMethods = new List<Action>()
    {
        SomeMethod1,
        SomeMethod2,
        await ExecuteParallelAsync, // ???
        SomeMethod3,
        SomeMethod4
    };

    for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
    {
        sequentialMethods.ElementAt( i ).Invoke();
    }
}

澄清:

private async Task ExecuteParallelAsync()
{
    List<Action> methods = new List<Action>()
    {
        MyMethod1,
        MyMethod2,
        MyMethod3
    };


    await Task.Run( () => { Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() ); } );            
}

sequenceMethodsList< Action >ExecuteParallelAsync不是 Action。 我已經嘗試拆分列表,就像建議的那樣。 不幸的是,它沒有幫助。

Marc 從原始代碼中建議的方式工作正常。 但是我想在每次(順序)方法調用之后做一些額外的事情,這就是為什么我嘗試使用列表和循環而不是普通方法調用的原因。

但是當我這樣做時,我再次面臨原來的問題,即 SomeMethod3 在 ExecuteParallelAsync 完成之前執行。

再一次, ExecuteParallelAsync中的所有內容都可以並且應該同時執行。 ExecuteSequential中的所有內容都必須按順序執行。

解決方案:

加布里埃爾是絕對正確的。 關鍵的聲明是這個

await Task.Run( () => { Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() ); } );

當我刪除每個異步和每個任務時,以便按順序執行所有內容,這一行是關鍵:

Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() );

當我使用最后一條語句時,一切正常。

感謝大家,你所有的想法、想法和努力都得到了幫助和贊賞。

我再次面臨原來的問題,即 SomeMethod3 在 ExecuteParallelAsync 完成之前執行

那么這不是異步編程的用例。 您的要求是這是同步的。

尤其如此,因為您說MyMethod1 / MyMethod2 / MyMethod3不是異步方法。 如果他們是,那將是完全不同的事情 但由於它們不是,我認為在這里嘗試使用asyncawait沒有任何價值。

但不要將異步與並行混淆。 看來您希望ExecuteParallelAsync中調用的方法並行運行,這很好。 你只是不需要asyncawait

例如:

private void ExecuteSequential()
{
    List<Action> sequentialMethods = new List<Action>()
    {
        SomeMethod1,
        SomeMethod2,
        ExecuteParallel,
        SomeMethod3,
        SomeMethod4
    };

    for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
    {
        sequentialMethods.ElementAt( i ).Invoke();
    }
}

private void ExecuteParallel()
{
    List<Action> methods = new List<Action>()
    {
        MyMethod1,
        MyMethod2,
        MyMethod3
    };

    Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() );            
}

您可以創建一個Action ,當調用它時將啟動任務並等待它完成,如下所示:

List<Action> sequentialMethods = new List<Action>()
{
    SomeMethod1,
    SomeMethod2,
    () => ExecuteParallelAsync().Wait(),
    SomeMethod3,
    SomeMethod4
};

這是一個版本:

private async Task  ExecuteSequential()
{
    var sequentialMethods = new List<Func<Task>>()
    {
        () => Task.Run(SomeMethod1),
        () => Task.Run(() => SomeMethod2("Hey!")), 
        ExecuteParallelAsync, 
        () => Task.Run(SomeMethod3),
        () => Task.Run(SomeMethod4)
    };

    for ( int i = 0 ; i < sequentialMethods.Count ; i++ )
    {
        Task t = sequentialMethods[i].Invoke(); 
        await t;
        // or just await sequentialMethods[i]();
    }
}

只是為了記錄, ExecuteSequential可能只是一個標准的異步方法(在順序執行方面非常好)。

private async Task ExecuteSequential()
{
  SomeMethod1();
  SomeMethod2();
  await ExecuteParallelAsync(); 
  SomeMethod3();
  SomeMethod4();
};

編輯:測試

代碼

class Program
{
    public void MyMethod1() => Console.WriteLine("||My1");
    public void MyMethod2() => Console.WriteLine("||My2");
    public void MyMethod3() => Console.WriteLine("||My3");

    private async Task ExecuteParallelAsync()
    {
        Console.WriteLine("||Start");
        List<Action> methods = new List<Action>() { MyMethod1, MyMethod2, MyMethod3 };

        await Task.Run(() => { Parallel.ForEach(methods, 
           (currentMethod) => currentMethod.Invoke()); }); // This could be just 'currentMethod();' (no Invoke())
        Console.WriteLine("||End");
    }


    public void SomeMethod1() => Console.WriteLine("Some1");
    public void SomeMethod2(string s) => Console.WriteLine($"Some2: {s}");
    public void SomeMethod3() => Console.WriteLine("Some3");
    public void SomeMethod4() => Console.WriteLine("Some4");

    private async Task ExecuteSequential()
    {
        var sequentialMethods = new List<Func<Task>>()
        {
           () => Task.Run(SomeMethod1),
           () => Task.Run(() => SomeMethod2("Hey!")),
           ExecuteParallelAsync,
           () => Task.Run(SomeMethod3),
           () => Task.Run(SomeMethod4)
        };

        for (int i = 0; i < sequentialMethods.Count; i++)
        {
            await sequentialMethods[i]();
        }
    }

    static async Task Main(string[] args)
    {
        await new Program().ExecuteSequential();
        Console.WriteLine("All done");
    }
}

Output

Some1
Some2: Hey!
||Start
||My3
||My2
||My1
||End
Some3
Some4
All done

My1My2My3將在執行之間更改順序,但始終在||Start||End內。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM