我有3个任务:
private async Task<Cat> FeedCat() {}
private async Task<House> SellHouse() {}
private async Task<Tesla> BuyCar() {}
Run Code Online (Sandbox Code Playgroud)
他们都需要在我的代码可以继续之前运行,我也需要每个代码的结果.结果没有任何共同之处
如何调用并等待3个任务完成然后获得结果?
等待故障任务(具有异常集的任务)时,await
将重新抛出存储的异常.如果存储的异常是a AggregateException
,它将重新抛出第一个并丢弃其余的异常.
我们如何使用await
并同时抛出原件AggregateException
以便我们不会意外丢失错误信息?
注意,当然可以考虑使用hacky解决方案(例如,试一试await
,然后调用Task.Wait
).我真的希望找到一个干净的解决方案.这里最好的做法是什么?
我想过使用自定义awaiter,但内置TaskAwaiter
包含很多魔法,我不知道如何完全重现.它调用TPL类型的内部API.我也不想重现所有这些.
如果你想玩它,这是一个简短的repro:
static void Main()
{
Run().Wait();
}
static async Task Run()
{
Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") };
await Task.WhenAll(tasks);
}
static Task CreateTask(string message)
{
return Task.Factory.StartNew(() => { throw new Exception(message); });
}
Run Code Online (Sandbox Code Playgroud)
只抛出两个例外中的一个Run
.
请注意,Stack Overflow上的其他问题无法解决此特定问题.建议重复时请小心.
我有以下代码,我想测试:
private Task _keepAliveTask; // get's assigned by object initializer
public async Task EndSession()
{
_cancellationTokenSource.Cancel(); // cancels the _keepAliveTask
await _logOutCommand.LogOutIfPossible();
await _keepAliveTask;
}
Run Code Online (Sandbox Code Playgroud)
重要的是,EndSession
只有`_keepAliveTask'结束后,Task才会结束.但是,我很难找到一种方法来可靠地测试它.
问题:我如何对EndSession
方法进行单元测试并验证等待Task
返回的方法.EndSession
_keepAliveTask
出于演示目的,单元测试可能如下所示:
public async Task EndSession_MustWaitForKeepAliveTaskToEnd()
{
var keepAliveTask = new Mock<Task>();
// for simplicity sake i slightly differ from the other examples
// by passing the task as method parameter
await EndSession(keepAliveTask);
keepAliveTask.VerifyAwaited(); // this is what i want to achieve
}
Run Code Online (Sandbox Code Playgroud)
进一步的标准: - …
在下面的代码中,task1和task2彼此独立,可以并行运行.以下两个实现有什么区别?
var task1 = GetList1Async();
var task2 = GetList2Async();
await Task.WhenAll(task1, task2);
var result1 = await task1;
var result2 = await task2;
Run Code Online (Sandbox Code Playgroud)
和
var task1 = GetList1Async();
var task2 = GetList2Async();
var result1 = await task1;
var result2 = await task2;
Run Code Online (Sandbox Code Playgroud)
我为什么要选择一个而不是另一个?
编辑:我想补充一点,返回类型的GetList1Async()和GetList2Async()方法是不同的.
使用async/await模型,我有一个方法,它对Web服务进行3次不同的调用,然后返回结果的并集.
var result1 = await myService.GetData(source1);
var result2 = await myService.GetData(source2);
var result3 = await myService.GetData(source3);
allResults = Union(result1, result2, result3);
Run Code Online (Sandbox Code Playgroud)
使用典型等待,这3个调用将彼此同步执行.我将如何让它们同时执行并在完成后加入结果?
我有一个 ASP .NET core Web API,它使用此处描述的排队后台任务 。
我已使用提供的代码示例并添加了IBackgroundTaskQueue
,BackgroundTaskQueue
和 ,QueuedHostedService
完全按照文章中所述。
在 my 中Startup.cs
,我仅注册一个QueuedHostedService
实例,如下所示:services.AddHostedService<QueuedHostedService>();
来自 WebApi 控制器的任务将被入队,然后出队并由QueuedHostedService
.
我希望允许多个后台处理线程使传入的任务出队并执行。我能想到的最直接的解决方案是QueuedHostedService
在我的Startup.cs
. 即,像这样:
int maxNumOfParallelOperations;
var isValid = int.TryParse(Configuration["App:MaxNumOfParallelOperations"], out maxNumOfParallelOperations);
maxNumOfParallelOperations = isValid && maxNumOfParallelOperations > 0 ? maxNumOfParallelOperations : 2;
for (int index = 0; index < maxNumOfParallelOperations; index++)
{
services.AddHostedService<QueuedHostedService>();
}
Run Code Online (Sandbox Code Playgroud)
我还注意到,由于 中的信号量BackgroundTaskQueue
,QueuedHostedService
实例并不是一直在工作,而是仅在队列中有新任务可用时才唤醒。
这个解决方案在我的测试中似乎效果很好。
但是,在这个特定的用例中 - 它真的是一个有效的、推荐的并行处理解决方案吗?
c# asp.net parallel-processing asp.net-core asp.net-core-hosted-services
我是异步编程的新手.我很想知道这些任务是否可以同时运行.考虑我有这个代码:
public async Task<IList<WebData>> GetAllAsync()
{
var twitterData = await ProvidetwitterDataAsync();
var facebookData = await ProvidefacebookDataAsync();
var linkedinData = await ProvidelinkedinDataAsync();
return twitterData .Concat(facebookData ).Concat(linkedinData ).ToList();
}
Run Code Online (Sandbox Code Playgroud)
我想因为我用过await twitterData
那个Task
应该完成,然后下一个Task
将开始,因为我想连续这三个列表的结果我用这种方式编写它,我想知道有没有办法可以同时完成这三个任务?这种实施方式是正确的还是有更好的方法?
我有两个可以并行运行的任务来提高性能:
var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();
await Task.WhenAll(task1, task2);
Run Code Online (Sandbox Code Playgroud)
现在,我确信这些任务已经完成.但根据我的理解(以及一些现实生活中的麻烦),如果我呼吁.Result
完成这些任务,即使它们完整,我也可能造成僵局?
从我正在阅读的内容来看,await
完成的任务只会返回结果,所以看起来就是这样的方式.这使我的代码看起来很时髦:
var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();
await Task.WhenAll(task1, task2);
var result1 = await task1;
var result2 = await task2;
Run Code Online (Sandbox Code Playgroud)
这是解决此问题并获得我的任务结果的正确方法吗?如果没有,问题是什么?有没有更好的方法来打开任务而不需要.Result
它们?
我把一个控制台/表单混合程序放在一起,为了实现我正在寻找的行为,我必须在一个线程中"运行"控制台,然后用另一个启动仪表板.
我用过BackgroundWorker
这个.基本上在Main
方法中我启动控制台后台工作器,它在其DoWork
块中执行正常的while循环以保持控制台运行.重复检查来自控制台的输入并将其传递给它相应的操作.
while (true && !Program.Shutdown)
{
String consoleInput = "";
consoleInput = Program.ReadFromConsole();
if (String.IsNullOrWhiteSpace(consoleInput))
continue;
try
{
Program.Shell(consoleInput);
}
catch (Exception ex)
{
Program.WriteToConsole(ex.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
在调用启动控制台的后台工作程序之后,即ConsoleBackgroundWorker.RunWorkerAsync()
调用执行加载序列的方法.
此加载序列CAN调用第二个后台工作程序,该工作程序在单独的线程内部启动仪表板.
现在我遇到的问题是加载序列结束时的循环.此循环可防止所有事务都关闭,直到两个后台工作程序都已完成(窗体关闭或控制台发送命令关闭)
while (ConsoleBackgroundWorker != null && DashboardBackgroundWorker != null)
{
/* I'm not sure of how else to fix this. But
* this corrects the high CPU usage reported
* in the Task Manager. */
System.Threading.Thread.Sleep(10);
}
Run Code Online (Sandbox Code Playgroud)
问题是CPU使用率,它一直保持在30%,这是没有你上面看到的那条线 System.Threading.Thread.Sleep(10)
我的问题是,这样可以吗?如果没有,我有什么解决方案?我注意到这确实纠正了这个问题,当应用程序没有做任何事情时,CPU现在的速度为0%.我也没有看到任何性能变化.但它还没有真正被"推",所以我不能肯定地说后者的观察.
c# ×9
async-await ×7
.net ×3
task ×2
.net-4.5 ×1
asp.net ×1
asp.net-core ×1
asp.net-core-hosted-services ×1
c#-5.0 ×1
unit-testing ×1