尝试理解TPL和async/ await在线程创建方面的区别.
我相信TPL(TaskFactory.StartNew)的工作方式类似于ThreadPool.QueueUserWorkItem它在线程池中的线程上排队工作.当然,除非您使用TaskCreationOptions.LongRunning哪个创建新线程.
我认为async/ await会以同样的方式工作:
TPL:
Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith(
(antecedent) => {
DoSomeWorkAfter();
},TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
Async/ Await:
await DoSomeAsyncWork();
DoSomeWorkAfter();
Run Code Online (Sandbox Code Playgroud)
会是相同的.从我一直在阅读它似乎async/ await只有"有时"创建一个新的线程.那么什么时候创建一个新线程,什么时候不创建一个新线程呢?如果您正在处理IO完成端口,我可以看到它不必创建新线程,但我认为它必须.我想我FromCurrentSynchronizationContext对此的理解总是有点模糊.我总是认为它本质上是UI线程.
我启动了一些并行任务,如下所示:
var tasks =
Enumerable.Range(1, 500)
.Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
.ToArray();
Run Code Online (Sandbox Code Playgroud)
然后加入他们
Task.WaitAll(tasks);
Run Code Online (Sandbox Code Playgroud)
在最后一行,我得到一个蓝色波浪形标记tasks,并带有警告信息:
__PRE__
我理解为什么我会收到这条消息,但有没有办法解决这个问题呢?(例如,像通用版本Task.WaitAll()?)
我是异步编程的新手,所以在浏览了一些异步样本代码之后,我想到了编写一个简单的异步代码
我创建了一个简单的Winform应用程序,在Form中我编写了以下代码.但它只是不起作用
private Task<string> methodAsync() {
Thread.Sleep(10000);
return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
}
private async void button1_Click(object sender, EventArgs e)
{
string s = await methodAsync();
MessageBox.Show(s);
}
Run Code Online (Sandbox Code Playgroud)
有人可以请点亮一下..
我有以下代码:
var task = Task.Factory.StartNew(CheckFiles, cancelCheckFile.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
private void CheckFiles()
{
//Do stuff
}
Run Code Online (Sandbox Code Playgroud)
我现在想修改CheckFiles以接受整数和BlockingCollection引用
private void CheckFiles(int InputID, BlockingCollection<string> BlockingDataCollection)
{
//Do stuff
}
Run Code Online (Sandbox Code Playgroud)
我似乎找不到像上面那样开始这项任务的方法.
你能帮我吗?
谢谢
我有以下测试代码:
void Button_Click(object sender, RoutedEventArgs e)
{
var source = new CancellationTokenSource();
var tsk1 = new Task(() => Thread1(source.Token), source.Token);
var tsk2 = new Task(() => Thread2(source.Token), source.Token);
tsk1.Start();
tsk2.Start();
source.Cancel();
try
{
Task.WaitAll(new[] {tsk1, tsk2});
}
catch (Exception ex)
{
// here exception is caught
}
}
void Thread1(CancellationToken token)
{
Thread.Sleep(2000);
// If the following line is enabled, the result is the same.
// token.ThrowIfCancellationRequested();
}
void Thread2(CancellationToken token)
{
Thread.Sleep(3000);
}
Run Code Online (Sandbox Code Playgroud)
在线程方法中,我不会抛出任何异常,但是我会TaskCanceledException进入try-catch启动任务的外部代码块.为什么会发生token.ThrowIfCancellationRequested(); …
我想安排一个任务以x ms开始,并能够在它开始之前取消它(或者只是在任务开始时).
第一次尝试就像是
var _cancelationTokenSource = new CancellationTokenSource();
var token = _cancelationTokenSource.Token;
Task.Factory.StartNew(() =>
{
token.ThrowIfCancellationRequested();
Thread.Sleep(100);
token.ThrowIfCancellationRequested();
}).ContinueWith(t =>
{
token.ThrowIfCancellationRequested();
DoWork();
token.ThrowIfCancellationRequested();
}, token);
Run Code Online (Sandbox Code Playgroud)
但我觉得应该有一个更好的方法,因为这会在睡眠中耗尽一个线程,在此期间它可以被取消.
我还有什么其他选择?
预告:伙计们,这个问题不是关于如何实施重试政策.这是关于正确完成TPL数据流块.
这个问题主要是我之前在ITargetBlock中重试策略的问题的延续.这个问题的答案是@ svick使用TransformBlock(源)和TransformManyBlock(目标)的智能解决方案.剩下的唯一问题是以正确的方式完成此块:等待所有重试首先完成,然后完成目标块.这是我最终得到的结果(它只是一个片段,不要过多关注非线程安全retries集):
var retries = new HashSet<RetryingMessage<TInput>>();
TransformManyBlock<RetryableMessage<TInput>, TOutput> target = null;
target = new TransformManyBlock<RetryableMessage<TInput>, TOutput>(
async message =>
{
try
{
var result = new[] { await transform(message.Data) };
retries.Remove(message);
return result;
}
catch (Exception ex)
{
message.Exceptions.Add(ex);
if (message.RetriesRemaining == 0)
{
if (failureHandler != null)
failureHandler(message.Exceptions);
retries.Remove(message);
}
else
{
retries.Add(message);
message.RetriesRemaining--;
Task.Delay(retryDelay)
.ContinueWith(_ => target.Post(message));
}
return null;
}
}, dataflowBlockOptions);
source.LinkTo(target);
source.Completion.ContinueWith(async …Run Code Online (Sandbox Code Playgroud) 请看下面的代码 -
static void Main(string[] args)
{
// Get the task.
var task = Task.Factory.StartNew<int>(() => { return div(32, 0); });
// For error handling.
task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); },
TaskContinuationOptions.OnlyOnFaulted);
// If it succeeded.
task.ContinueWith(t => { Console.WriteLine(t.Result); },
TaskContinuationOptions.OnlyOnRanToCompletion);
Console.ReadKey();
Console.WriteLine("Hello");
}
private static int div(int x, int y)
{
if (y == 0)
{
throw new ArgumentException("y");
}
return x / y;
}
Run Code Online (Sandbox Code Playgroud)
如果我在发布模式下执行代码,输出为"发生了一个或多个错误",一旦我点击"Enter"键,"Hello"也会显示.如果我在调试模式下运行代码,输出与但是在IDE中调试时,当控件执行该行时,会出现IDE异常消息("用户代码中未处理的异常")
throw new ArgumentException("y");
Run Code Online (Sandbox Code Playgroud)
如果我从那里继续,程序不会崩溃并显示与发布模式相同的输出.这是处理异常的正确方法吗?
我想换我周围的TPL,新的头async/ await在C#5的特性,和的奥秘TaskCompletionSource.
有一件事情是我不明白是什么时候使用SetResult,SetException以及SetCancel与TrySetResult,TrySetException和TrySetCancel.
这就是MSDN所说的:
如果任务已经处于以下三种最终状态之一,则此操作将返回false:RanToCompletion,Faulted或Cancelled.
如果已经处理了基础Task,则此方法也返回false.
好吧,我明白了,但它并没有真正提供关于何时或为何使用其中一个的指导.
那么,这笔交易是什么?
我正在使用Parallel.ForEach并且我正在做一些数据库更新,现在没有设置MaxDegreeOfParallelism,双核处理器机器导致sql客户端超时,否则四核处理器机器不知何故不会超时.
现在我无法控制我的代码运行的哪种处理器内核可用,但是我可以使用MaxDegreeOfParallelism更改某些设置,这些设置可能会同时运行较少的操作而不会导致超时?
我可以增加超时但它不是一个好的解决方案,如果在较低的CPU上我可以同时处理较少的操作,这将减少对CPU的负载.
好的我也读过所有其他帖子和MSDN,但是将MaxDegreeOfParallelism设置为较低值会让我的四核机器遭受损失吗?
例如,无论如何,如果CPU有两个内核,那么使用20,如果CPU有四个内核,那么40?
c# .net-4.0 parallel-extensions task-parallel-library parallel.foreach
c# ×9
.net ×3
async-await ×3
c#-5.0 ×3
.net-4.0 ×2
asynchronous ×1
covariance ×1
generics ×1
task ×1
tpl-dataflow ×1