我正在阅读一本关于C#任务并行库的书,并且有以下示例,但是永远不会触发TaskScheduler.UnobservedTaskException处理程序.任何人都可以给我任何线索,为什么?
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
((AggregateException)eventArgs.Exception).Handle(ex =>
{
Console.WriteLine("Exception type: {0}", ex.GetType());
return true;
});
};
Task task1 = new Task(() =>
{
throw new ArgumentNullException();
});
Task task2 = new Task(() => {
throw new ArgumentOutOfRangeException();
});
task1.Start();
task2.Start();
while (!task1.IsCompleted || !task2.IsCompleted)
{
Thread.Sleep( 5000 );
}
Console.WriteLine("done");
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud) 我试图理解为什么以及何时应该使用async控制器操作.最终,当我await在其中使用时,它将等待操作完成以返回视图.
例如
public async Task<ActionResult> TryMe()
{
await SomeActionAsync();
return View();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果我使用async或不使用async,则Action将花费相同的时间来执行.
如果我没有尝试并行运行至少2个慢速操作(并非彼此依赖),我认为没有任何理由使用async控制器操作.
如果我错了,请纠正我.我想我在这里遗漏了一些东西.
asp.net asynchronous task-parallel-library async-await asp.net-mvc-4
我有一份任务列表,我想等待.我在等
await TaskEx.WhenAll(MyViewModel.GetListOfTasks().ToArray());
Run Code Online (Sandbox Code Playgroud)
MyViewModel.GetListOfTasks()返回任务列表:
var tasksList = new List<Task>();
foreach (var item in Items)
{
tasksList.Add(item.MyTask());
}
Run Code Online (Sandbox Code Playgroud)
现在,我想返回虚拟任务,这将立即完成.但是,TaskEx.WhenAll会永远等待它:
public Task<bool> MyTask()
{
return new Task<bool>(() => false);
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能返回任务,这将立即完成?
以下代码片段之间是否有任何区别?如果是这样,什么?
myList.AsParallel().ForAll(i => { /*DO SOMETHING*/ });
和
Parallel.ForEach(mylist, i => { /*DO SOMETHING*/ });
主线程是否会等待所有子线程完成?在MVC应用程序中,如果我在控制器操作中进行并行处理,主线程完成后子线程会发生什么.他们会被中止还是会在主线完成后完成?
有一个在任务中执行的过程.我不希望其中一个同时执行.
这是检查任务是否已在运行的正确方法吗?
private Task task;
public void StartTask()
{
if (task != null && (task.Status == TaskStatus.Running || task.Status == TaskStatus.WaitingToRun || task.Status == TaskStatus.WaitingForActivation))
{
Logger.Log("Task has attempted to start while already running");
}
else
{
Logger.Log("Task has began");
task = Task.Factory.StartNew(() =>
{
// Stuff
});
}
}
Run Code Online (Sandbox Code Playgroud) 此问题已由EF数据上下文 - 异步/等待和多线程触发.我已经回答了那个,但没有提供任何最终的解决方案.
最初的问题是,有许多有用的.NET API(如Microsoft Entity Framework DbContext),它们提供了设计用于的异步方法await,但它们被记录为不是线程安全的.这使它们非常适合在桌面UI应用程序中使用,但不适用于服务器端应用程序.[编辑] 这可能实际上并不适用DbContext,这是微软关于EF6线程安全的声明,自己判断. [/ EDITED]
还有一些已建立的代码模式属于同一类别,例如调用WCF服务代理OperationContextScope(在此处和此处询问),例如:
using (var docClient = CreateDocumentServiceClient())
using (new OperationContextScope(docClient.InnerChannel))
{
return await docClient.GetDocumentAsync(docId);
}
Run Code Online (Sandbox Code Playgroud)
这可能会失败,因为OperationContextScope在其实现中使用线程本地存储.
问题的根源AspNetSynchronizationContext是在异步ASP.NET页面中使用,以便从ASP.NET线程池中使用更少的线程来满足更多HTTP请求.使用时AspNetSynchronizationContext,await可以在与启动异步操作的线程不同的线程上对延续进行排队,同时将原始线程释放到池中,并可用于提供另一个HTTP请求.这大大提高了服务器端代码的可扩展性.该机制在It's All About the SynchronizationContext中有详细描述,必须阅读.因此,虽然没有涉及并发API访问,但潜在的线程切换仍然阻止我们使用上述API.
我一直在考虑如何在不牺牲可扩展性的情况下解决这个问题.显然,恢复这些API的唯一方法是维护可能受线程切换影响的异步调用范围的线程关联.
假设我们有这样的线程亲和力.这些调用中的大多数都是IO绑定的(没有线程).当异步任务处于挂起状态时,它所源自的线程可用于提供另一个类似任务的延续,该结果已经可用.因此,它不应该过多地损害可伸缩性.这种方法并不新鲜,事实上,Node.js成功使用了类似的单线程模型 …
我想向服务器发送请求并处理返回的值:
private static string Send(int id)
{
Task<HttpResponseMessage> responseTask = client.GetAsync("aaaaa");
string result = string.Empty;
responseTask.ContinueWith(x => result = Print(x));
responseTask.Wait(); // it doesn't wait for the completion of the response task
return result;
}
private static string Print(Task<HttpResponseMessage> httpTask)
{
Task<string> task = httpTask.Result.Content.ReadAsStringAsync();
string result = string.Empty;
task.ContinueWith(t =>
{
Console.WriteLine("Result: " + t.Result);
result = t.Result;
});
task.Wait(); // it does wait
return result;
}
Run Code Online (Sandbox Code Playgroud)
我使用Task得当吗?我不这么认为,因为该Send()方法string.Empty每次都Print返回,同时返回正确的值.
我究竟做错了什么?如何从服务器获得正确的结果?
假设以下同步代码:
try
{
Foo();
Bar();
Fubar();
Console.WriteLine("All done");
}
catch(Exception e) // For illustration purposes only. Catch specific exceptions!
{
Console.WriteLine(e);
}
Run Code Online (Sandbox Code Playgroud)
现在假设所有这些方法都有一个异步的对应,我不得不使用那些由于某种原因,所以简单地包裹了整个事情的新任务是不是一种选择.
我将如何实现相同的行为?
我对"相同"的意思是:
我唯一能想到的就是可怕:
var fooTask = FooAsync();
fooTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fooTask.ContinueWith(
t =>
{
var barTask = BarAsync();
barTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
barTask.ContinueWith(
t =>
{
var fubarTask = FubarAsync();
fubarTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fubarTask.ContinueWith(
t => Console.WriteLine("All done"),
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);
Run Code Online (Sandbox Code Playgroud)
请注意:
async/await不可能.但是,如果它可以async/await随意显示如何工作.我正在尝试做这样的事情:
foreach (var o in ObjectList)
{
CalculateIfNeedToMakeTaskForO(o);
if (yes)
TaskList.Add(OTaskAsync());
}
Run Code Online (Sandbox Code Playgroud)
现在我想等待所有这些任务完成.除了做
foreach(var o in ObjectList)
{
Result.Add("result for O is: "+await OTaskAsync());
}
Run Code Online (Sandbox Code Playgroud)
有什么我能做的吗?(更好,更优雅,更"正确")
好的,我的问题非常简单.为什么这段代码不会抛出TaskCancelledException?
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationTokenSource(500).Token).Result;
Console.WriteLine(v); // this outputs 10 - instead of throwing error.
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
但这一个有效
static void Main()
{
var v = Task.Run(() =>
{
Thread.Sleep(1000);
return 10;
}, new CancellationToken(true).Token).Result;
Console.WriteLine(v); // this one throws
Console.Read();
}
Run Code Online (Sandbox Code Playgroud) .net c# task-parallel-library cancellationtokensource cancellation-token