C# 什么时候是连续的还是并发的?
每次运行以下命令时,都会捕获Mike的异常 什么时候每个任务之间都有连续上下文,还是所有任务都同时运行?如果是同时发生的,为什么迈克的异常总是被发现而不是米奇的。我拖延了迈克的时间,以便给米奇一个机会。如果它是连续的,那么使它并发涉及到什么?在进行web请求/文件处理时是否会应用并发执行 假设这段代码更为严肃,那么这是异步的合理方法吗?场景是几个方法——Jason、Mitch和Mike——在不阻塞的情况下并发运行,并在全部完成后继续事件处理程序?围绕我的异常处理的幼稚实现,我应该注意什么?需要注意的任何问题或潜在问题C# 什么时候是连续的还是并发的?,c#,async-await,C#,Async Await,每次运行以下命令时,都会捕获Mike的异常 什么时候每个任务之间都有连续上下文,还是所有任务都同时运行?如果是同时发生的,为什么迈克的异常总是被发现而不是米奇的。我拖延了迈克的时间,以便给米奇一个机会。如果它是连续的,那么使它并发涉及到什么?在进行web请求/文件处理时是否会应用并发执行 假设这段代码更为严肃,那么这是异步的合理方法吗?场景是几个方法——Jason、Mitch和Mike——在不阻塞的情况下并发运行,并在全部完成后继续事件处理程序?围绕我的异常处理的幼稚实现,我应该注意什么?需要注
private async void button1_Click(object sender,EventArgs e)
{
try
{
AsyncJason c1 = new AsyncJason();
await c1.Hello();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public class AsyncJason
{
public AsyncJason()
{
}
public async Task Hello()
{
var j = await GetJasonAsync();
string[] dankeSchon = await Task.WhenAll(new Task<string>[] {GetJasonAsync(), GetMikeAsync(), GetMitchAsync()});
}
private async Task<string> GetJasonAsync()
{
var result = await Task.Run<string>(() => GetJason());
return result;
}
private string GetJason()
{
return "Jason";
}
private async Task<string> GetMitchAsync()
{
var result = await Task.Run<string>(() => GetMitch());
return result;
}
private string GetMitch()
{
throw new ArgumentException("Mitch is an idiot", "none");
}
private async Task<string> GetMikeAsync()
{
await Task.Delay(3000);
var result = await Task.Run<string>(() => GetMike());
return result;
}
private string GetMike()
{
throw new ArgumentException("Mike is an idiot", "none");
}
}
private async void按钮1\u单击(对象发送方,事件参数e)
{
尝试
{
AsyncJason c1=新的AsyncJason();
等待c1.你好();
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
公共类异步
{
公共服务
{
}
公共异步任务Hello()
{
var j=等待GetJasonAsync();
string[]dankeSchon=wait Task.WhenAll(新任务[]{GetJasonAsync(),GetMikeAsync(),GetMitchAsync()});
}
专用异步任务GetJasonAsync()
{
var result=wait Task.Run(()=>GetJason());
返回结果;
}
私有字符串GetJason()
{
返回“Jason”;
}
专用异步任务GetMitchAsync()
{
var result=wait Task.Run(()=>GetMitch());
返回结果;
}
私有字符串GetMitch()
{
抛出新的ArgumentException(“米奇是个白痴”,“没有”);
}
专用异步任务GetMikeAsync()
{
等待任务。延迟(3000);
var result=wait Task.Run(()=>GetMike());
返回结果;
}
私有字符串GetMike()
{
抛出新的ArgumentException(“迈克是个白痴”,“没有”);
}
}
什么时候是连续的还是并发的
这个问题实际上并不适用。当所有基础任务完成时,whalll
的任务完成。如何做到这一点是它的事
在异常方面,任务
的异常
属性包含一个聚合异常
,该异常包含所有基础任务引发的所有异常
当您等待一个包含表示多个异常的聚合异常的任务时,它将打开并重新抛出该列表中的第一个异常,而不是包含所有异常的aggregateeexception
创建aggregateeexception
时,它(显然;我不知道这是否在任何地方得到保证)会根据所有时传递给的任务的顺序列出异常,而不是根据这些任务完成的顺序
如果您担心丢失的异常,那么您应该存储它返回的任务,以便您可以检查所有异常,或者只是重新播放包装的聚合异常
,即:
public async Task Hello()
{
var j = await GetJasonAsync();
var task = Task.WhenAll(new Task<string>[] { GetJasonAsync(), GetMikeAsync(), GetMitchAsync() });
try
{
string[] dankeSchon = await task;
}
catch (Exception)
{
throw task.Exception;
}
}
基本上,这里的想法是为每个任务创建一个TaskCompletionSource
,为提供给我们的每个任务添加一个延续,然后当任何任务完成时,我们将尚未完成的TaskCompletionSource标记为刚完成任务的结果
利用这个,我们现在可以写:
public async Task Hello()
{
var j = await GetJasonAsync();
var tasks = new[] { GetJasonAsync(), GetMikeAsync(), GetMitchAsync() };
string[] dankeSchon = await Task.WhenAll(tasks.Order());
}
并且异常将是第一个抛出的异常。当无法控制任务的执行方式时(即所有任务都可以在当所有执行时完成)…将不会抛出任务。异常代码>吹走异常的堆栈跟踪?@ScottChamberlain的聚合异常,是的。在内部异常中,我不希望如此。我记得看到过一个C#5.0工具的示例,可以使用它在不清除堆栈的情况下重新引发异常,但我没有花时间再次查找它;理论上可以在这里应用。
public async Task Hello()
{
var j = await GetJasonAsync();
var tasks = new[] { GetJasonAsync(), GetMikeAsync(), GetMitchAsync() };
string[] dankeSchon = await Task.WhenAll(tasks.Order());
}