static async void Main(string[] args)
{
Task t = new Task(() => { throw new Exception(); });
try
{
t.Start();
t.Wait();
}
catch (AggregateException e)
{
// When waiting on the task, an AggregateException is thrown.
}
try
{
t.Start();
await t;
}
catch (Exception e)
{
// When awating on the task, the exception itself is thrown.
// in this case a regular Exception.
}
}
Run Code Online (Sandbox Code Playgroud)
在TPL中,当在Task中抛出异常时,它被包装为AggregateException.
但是使用await关键字时也不会发生同样的情况.
这种行为的解释是什么?
c# exception-handling parallel-extensions task-parallel-library async-await
场景:循环中的异步任务执行一个方法,该方法包含随程序继续而变化的参数:
while(this._variable < 100)
{
this._variable++;
var aTask = Task.Factory.StartNew(() =>
{
aList.add(this._variable);
update(this._savePoint);
});
}
Run Code Online (Sandbox Code Playgroud)
如果循环运行得比任务完成的速度快,列表是否会添加变量的当前值,还是本地保存的变量并添加原始值?
我将在我的应用程序上运行许多任务.由于某种原因,每组任务都在运行.我想命名这些任务,所以当我观看Parallel Tasks窗口时,我可以轻松识别它们.
从另一个角度来看,考虑我在框架级别使用任务来填充列表.使用我的框架的开发人员也在为她的工作使用任务.如果她查看并行任务窗口,她会发现一些不知道的任务.我想命名任务,以便她可以将框架任务与她的任务区分开来.
如果有这样的API会很方便:
var task = new Task(action, "Growth calculation task")
Run Code Online (Sandbox Code Playgroud)
或者可能:
var task = Task.Factory.StartNew(action, "Populating the datagrid")
Run Code Online (Sandbox Code Playgroud)
甚至在工作时 Parallel.ForEach
Parallel.ForEach(list, action, "Salary Calculation Task"
Run Code Online (Sandbox Code Playgroud)
可以命名任务吗?
是否有可能得到Parallel.ForEach一个命名结构(也许使用Lambda),所以它创造了这样的命名任务?
我错过了某个地方的API吗?
我还尝试使用继承的任务来覆盖它的ToString().但不幸的是,Parallel Tasks窗口不使用ToString()!
class NamedTask : Task
{
private string TaskName { get; set; }
public NamedTask(Action action, string taskName):base(action)
{
TaskName = taskName;
}
public override string ToString()
{
return TaskName;
}
}
Run Code Online (Sandbox Code Playgroud) 读取Parallel.ForEach后继续产生新线程我仍然怀疑它是否是计算并发线程数的正确方法?
我看到的是,该方法计算同时输入但未完成的迭代(循环)的数量Parallel.ForEach.
它是传递正确数量的同时运行线程的并发线程数的同义词吗?
我不是专家,但我可以想象:
无论如何,如何直接计算.NET进程的运行线程数,最好是(C#)代码?
更新:
所以,如果要遵循Jeppe Stig Nielsen的回答并使用计数
directThreadsCount = Process.GetCurrentProcess().Threads.Count;
Run Code Online (Sandbox Code Playgroud)
然后输出,在Release(threadsCount == 7)和Debug(threadsCount == 15)模式下非常相似:
[Job 0 complete. 2 threads remaining but directThreadsCount == 7
[Job 1 complete. 1 threads remaining but directThreadsCount == 7
[Job 2 complete. 2 threads remaining but directThreadsCount == 7
[Job 4 complete. 2 threads remaining but directThreadsCount == 7
[Job 5 complete. 2 threads remaining but directThreadsCount == 7
[Job 3 complete. 2 …Run Code Online (Sandbox Code Playgroud) c# debugging multithreading visual-studio task-parallel-library
我有一个应用程序从不同的来源提取相当数量的数据.本地数据库,联网数据库和Web查询.任何这些都可能需要几秒钟才能完成.所以,首先我决定并行运行这些:
Parallel.Invoke(
() => dataX = loadX(),
() => dataY = loadY(),
() => dataZ = loadZ()
);
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,所有三个并行执行,但是在最后一个块完成之前,整个块上的执行都不会返回.
接下来,我决定在应用程序中添加一个微调器或"忙指示器".我不想阻止UI线程或者微调器不会旋转.所以这些需要以async模式运行.但是如果我在异步模式下运行所有这三个,那么它们的影响就会"同步"发生,而不是与UI在同一个线程中.我仍然希望他们并行运行.
spinner.IsBusy = true;
Parallel.Invoke(
async () => dataX = await Task.Run(() => { return loadX(); }),
async () => dataY = await Task.Run(() => { return loadY(); }),
async () => dataZ = await Task.Run(() => { return loadZ(); })
);
spinner.isBusy = false;
Run Code Online (Sandbox Code Playgroud)
现在,Parallel.Invoke不会等待方法完成,并且微调器立即关闭.更糟糕的是,dataX/Y/Z为空,稍后会发生异常.
这里有什么正确的方法?我应该使用BackgroundWorker吗?我希望能够利用.Net 4.5的功能.
var buffer = new BufferBlock<object>();
var producer = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
buffer.Post(null);
Console.WriteLine("Post " + buffer.Count);
}
});
var consumer = Task.Run(async () =>
{
while (await buffer.OutputAvailableAsync())
{
IList<object> items;
buffer.TryReceiveAll(out items);
Console.WriteLine("TryReceiveAll " + buffer.Count);
}
});
await Task.WhenAll(consumer, producer);
Run Code Online (Sandbox Code Playgroud)
生产者应该每隔100毫秒将项目发布到缓冲区,并且消费者应该清除缓冲区中的所有项目并异步地等待更多项目显示.
实际发生的是制作人清除所有项目一次,然后再也不会超越OutputAvailableAsync.如果我切换消费者逐个删除项目,它将作为例外工作:
while (await buffer.OutputAvailableAsync())
{
object item;
while (buffer.TryReceive(out item)) ;
}
Run Code Online (Sandbox Code Playgroud)
我误会了什么吗?如果没有,问题是什么?
请参阅下面的伪代码
//Single or multiple Producers produce using below method
void Produce(object itemToQueue)
{
concurrentQueue.enqueue(itemToQueue);
consumerSignal.set;
}
//somewhere else we have started a consumer like this
//we have only one consumer
void StartConsumer()
{
while (!concurrentQueue.IsEmpty())
{
if (concurrentQueue.TrydeQueue(out item))
{
//long running processing of item
}
}
consumerSignal.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)
我如何移植这种模式,我从远古时代就开始使用taskfactory创建的任务和net 4的新信号功能.换句话说,如果有人用net 4编写这个模式,它会是什么样子?伪代码很好.如你所见,我已经使用.net 4 concurrentQueue了.如何使用任务并可能使用一些新的信令机制.谢谢
通过Jon/Dan解决我的问题.甜.没有手动信号或while(true)或while(itemstoProcess)类型循环像过去那样
//Single or multiple Producers produce using below method
void Produce(object itemToQueue)
{
blockingCollection.add(item);
}
//somewhere else we have started a consumer like this
//this supports …Run Code Online (Sandbox Code Playgroud) 据我所知,Task和Thread之间的区别在于,任务发生在线程池中,而线程是我需要自己管理的东西..(并且该任务可以取消并返回到线程池中他的任务结束)
但在一些博客中,我读到如果操作系统需要创建任务并创建thread =>,那么创建(和销毁)任务将更容易.
有人可以解释为什么创建任务很简单那个线程?
(或许我在这里遗漏了一些东西......)
考虑以下(基于默认的MVC模板),这是在后台发生的一些"东西"的简化版本 - 它完成得很好,并显示预期的结果,20:
public ActionResult Index()
{
var task = SlowDouble(10);
string result;
if (task.Wait(2000))
{
result = task.Result.ToString();
}
else
{
result = "timeout";
}
ViewBag.Message = result;
return View();
}
internal static Task<long> SlowDouble(long val)
{
TaskCompletionSource<long> result = new TaskCompletionSource<long>();
ThreadPool.QueueUserWorkItem(delegate
{
Thread.Sleep(50);
result.SetResult(val * 2);
});
return result.Task;
}
Run Code Online (Sandbox Code Playgroud)
但是,现在如果我们async在混合中添加一些:
public static async Task<long> IndirectSlowDouble(long val)
{
long result = await SlowDouble(val);
return result;
}
Run Code Online (Sandbox Code Playgroud)
并将路线中的第一行更改为:
var task = IndirectSlowDouble(10);
Run Code Online (Sandbox Code Playgroud)
然后它不起作用 ; 它反而超时了.如果我们添加断点,方法 …
我正在阅读和学习有关ThreadSchedulerTasks的文章和文章,并且遇到了ThreadPool.UnsafeQueueUserWorkItem一个关于自己的ThreadSchedulers 的MSDN示例中使用的函数.在关于UnsafeQueueUserWorkItem的MSDN 描述中,有一个很大的警告,即该函数可能是一个安全漏洞,并且它" 不会传播调用堆栈 ".
唯一的联系是QueueUserWorkItem- 从名称 - 似乎是"安全的对应物"?但是没有提到任何关于调用堆栈的事情.
传播堆栈到底意味着什么?在工作开始之前复制它?为什么另一个线程需要调用线程的堆栈呢?我认为他们从一个新的空堆栈开始.毕竟,当线程函数返回时,它不会继续执行调度任务的函数,对吧?
c# ×9
.net ×4
async-await ×3
.net-4.0 ×2
asp.net ×1
asp.net-mvc ×1
asynchronous ×1
debugging ×1
pfx ×1
scope ×1
tpl-dataflow ×1