扩展 C# 异步/等待 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() ); } );            
}

sequentialMethods是一个List<<em>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");
}
}

输出

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

My1My2My3将在执行之间更改顺序,但始终在||Start||End内。

最新更新