标签: task-parallel-library

TPL和async/await之间的区别(线程处理)

尝试理解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线程.

multithreading task-parallel-library async-await c#-5.0

61
推荐指数
2
解决办法
2万
查看次数

是否有通用的Task.WaitAll?

我启动了一些并行任务,如下所示:

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()?)

c# generics covariance task-parallel-library

60
推荐指数
4
解决办法
9814
查看次数

无法将类型'string'隐式转换为'System.Threading.Tasks.Task <string>'

我是异步编程的新手,所以在浏览了一些异步样本代码之后,我想到了编写一个简单的异步代码

我创建了一个简单的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)

有人可以请点亮一下..

c# task-parallel-library async-await

60
推荐指数
3
解决办法
11万
查看次数

使用Task.Factory.StartNew传递方法参数

我有以下代码:

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)

我似乎找不到像上面那样开始这项任务的方法.

你能帮我吗?

谢谢

.net c# .net-4.0 task-parallel-library

59
推荐指数
4
解决办法
12万
查看次数

为什么会发生TaskCanceledException?

我有以下测试代码:

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(); …

c# task-parallel-library c#-5.0

55
推荐指数
1
解决办法
5万
查看次数

正确的方法来延迟任务的开始

我想安排一个任务以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)

但我觉得应该有一个更好的方法,因为这会在睡眠中耗尽一个线程,在此期间它可以被取消.

我还有什么其他选择?

.net c# task-parallel-library

53
推荐指数
3
解决办法
4万
查看次数

实现可重试块的正确完成

预告:伙计们,这个问题不是关于如何实施重试政策.这是关于正确完成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)

c# task-parallel-library tpl-dataflow

53
推荐指数
1
解决办法
3999
查看次数

在任务中继续处理异常的正确方法

请看下面的代码 -

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)

如果我从那里继续,程序不会崩溃并显示与发布模式相同的输出.这是处理异常的正确方法吗?

.net c# task task-parallel-library

52
推荐指数
4
解决办法
5万
查看次数

TaskCompletionSource:何时使用SetResult()与TrySetResult()等

我想换我周围的TPL,新的头async/ await在C#5的特性,和的奥秘TaskCompletionSource.

有一件事情是我不明白是什么时候使用SetResult,SetException以及SetCancelTrySetResult,TrySetExceptionTrySetCancel.

这就是MSDN所说的:

如果任务已经处于以下三种最终状态之一,则此操作将返回false:RanToCompletion,Faulted或Cancelled.

如果已经处理了基础Task,则此方法也返回false.

好吧,我明白了,但它并没有真正提供关于何时或为何使用其中一个的指导.

那么,这笔交易是什么?

c# asynchronous task-parallel-library async-await c#-5.0

50
推荐指数
1
解决办法
1万
查看次数

MaxDegreeOfParallelism有什么作用?

我正在使用Parallel.ForEach并且我正在做一些数据库更新,现在没有设置MaxDegreeOfParallelism,双核处理器机器导致sql客户端超时,否则四核处理器机器不知何故不会超时.

现在我无法控制我的代码运行的哪种处理器内核可用,但是我可以使用MaxDegreeOfParallelism更改某些设置,这些设置可能会同时运行较少的操作而不会导致超时?

我可以增加超时但它不是一个好的解决方案,如果在较低的CPU上我可以同时处理较少的操作,这将减少对CPU的负载.

好的我也读过所有其他帖子和MSDN,但是将MaxDegreeOfParallelism设置为较低值会让我的四核机器遭受损失吗?

例如,无论如何,如果CPU有两个内核,那么使用20,如果CPU有四个内核,那么40?

c# .net-4.0 parallel-extensions task-parallel-library parallel.foreach

49
推荐指数
3
解决办法
5万
查看次数