标签: task-parallel-library

TaskCreationOptions.LongRunning选项和ThreadPool

TPL使用任务计划程序来协调任务.根据官方文档,默认任务调度程序使用线程池,但如果显示TaskCreationOptions.LongRunning选项,则它将为该任务创建专用线程(A).

问题:截至目前,Visual Studio 2010的MSDN文档尚未就绪,当前的在线MSDN尚未最终确定; 有谁知道(A)是真还是假?

c# scheduled-tasks .net-4.0 threadpool task-parallel-library

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

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

解雇ASP.NET MVC

我正在寻找有关火灾最佳实践的信息并忘记asp.net mvc行动...基本上我想要一个移动客户端来打电话; 服务器启动异步任务; 然后尽快返回移动客户端.

但我想确保,假设没有异常,异步任务将成功完成.显然有几个不同的选择:

  • 创建一个新线程
  • 在ThreadPool上排队工作项
  • 开始异步委托调用
  • 启动任务

我认为任务将是这里的最佳选择,但想从SO获得想法.

编辑:根据已有的一些答案澄清:客户端不需要回复.我希望一旦服务器开始异步任务,HTTP请求就会尽快完成.我知道客户端上的异步模式,但是我想限制移动设备维持连接打开所需的时间.此外,希望避免有一个单独的进程轮询或推送消息(通过队列,总线等),因为这是过度的.我只想在数据库中记录某些内容,在IO完成之前,客户端不需要保持连接.

asp.net-mvc asynchronous task-parallel-library

24
推荐指数
2
解决办法
9044
查看次数

最佳实践LongRunning任务创建

对于需要使用.Net 4中的Task API运行的后台线程,这是一个很好的设计吗?我唯一担心的是,如果我们要取消该任务,我将如何做到这一点?我知道我可以设置ProgramEnding,true但我知道CancellationTokenTask API中有一个.

这只是一个示例代码示例,以便一个线程将添加到集合中,另一个线程将从中删除.任务设置为LongRunning,因为这需要在程序运行时连续运行

private void RemoveFromBlockingCollection()
{
    while (!ProgramEnding)
    {
       foreach (var x in DataInQueue.GetConsumingEnumerable())
       {
          Console.WriteLine("Task={0}, obj={1}, Thread={2}"
                          , Task.CurrentId, x + " Removed"
                          , Thread.CurrentThread.ManagedThreadId);
       }
    }
}

private void button1_Click(object sender, EventArgs e)
{
   DataInQueue = new BlockingCollection<string>();
   var t9 = Task.Factory.StartNew(RemoveFromBlockingCollection
                                 , TaskCreationOptions.LongRunning);

   for (int i = 0; i < 100; i++)
   {
     DataInQueue.Add(i.ToString());
     Console.WriteLine("Task={0}, obj={1}, Thread={2}", 
                       Task.CurrentId, i + " Added", 
                       Thread.CurrentThread.ManagedThreadId);
     Thread.Sleep(100);
   }
   ProgramEnding = true; …
Run Code Online (Sandbox Code Playgroud)

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

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

Task.Factory.StartNew vs Async方法

可能是一个微不足道的问题,但它可能有助于我的基本理解.

以下两个实现之间是否有任何重要区别?

  1. Task.Factory.StartNew:

    public Task<string> ReadAllTextAsync(string path) {
        return Task.Factory.StartNew(() => File.ReadAllText(path));
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 异步方法StreamReader:

    public async Task<string> ReadAllTextAsync(string path) {
        using (var stream = File.OpenRead(path))
        using (var reader = new StreamReader(stream)) {
            return await reader.ReadToEndAsync();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

c# task-parallel-library async-await

24
推荐指数
1
解决办法
7392
查看次数

等待.NET 4.0:有意义的堆栈跟踪

我有一个使用.NET 4.0的C#控制台应用程序项目,安装了Microsoft.Bcl.Async软件包.我用这个代码:

internal class Program
{
    private static void Main(string[] args)
    {
        Foo().Wait();
    }

    static void Log(Exception ex)
    {

    }

    private static async Task Foo()
    {
        try
        {
            await DoSomething();
        }
        catch (Exception ex)
        {
            Log(ex);
        }
    }

    private static async Task DoSomething()
    {
        throw new DivideByZeroException();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我在Log方法中放置一个断点,我得到了DivideByZero异常,但我看到的堆栈跟踪是:

at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.GetResult()
at AsyncStacks.Program.<Foo>d__0.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 25
Run Code Online (Sandbox Code Playgroud)

这个堆栈跟踪几乎没用,因为它没有告诉我实际抛出异常的位置.

如果我将项目更改为目标.NET 4.5,我会得到一个更有用的异常:

at AsyncStacks.Program.<DoSomething>d__3.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 35
--- End of stack trace from …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous exception-handling task-parallel-library async-await

24
推荐指数
1
解决办法
2707
查看次数

Task.WhenAny - 剩余的正在运行的任务会发生什么?

我有以下代码:

List<Task<bool>> tasks = tasksQuery.ToList();
while (tasks.Any())
{
    Task<bool> completedTask = await Task.WhenAny(tasks);
    if (await completedTask)
        return true;

    tasks.Remove(completedTask);
}
Run Code Online (Sandbox Code Playgroud)

它并行启动任务.当第一个完成的任务返回true时,方法返回true.

我的问题是:

所有剩余的任务已经启动并且可能仍然在后台运行会发生什么? 这是执行异步,并行和在第一个条件发生后应该返回的代码的正确方法,还是最好逐个启动它们并等待单独进行?

谢谢

c# task-parallel-library async-await

24
推荐指数
1
解决办法
8353
查看次数

如何在不抛出TaskCanceledExceptions的情况下等待任务?

我有一个创建一些任务的方法,然后在返回之前用WaitAll等待它们.问题是,如果这些任务被取消,那么WaitAll会抛出一个包含大量TaskCanceledExceptionAggregateException.

这意味着WaitAll将在两种不同的情况下抛出异常:

  • 表示真正错误的例外情况.这意味着我们不知道如何处理这种情况; 它们需要作为未处理的异常进行传播,直到它们最终终止进程.
  • 表示用户单击"取消"按钮的例外情况.这意味着任务被取消并清理,程序应继续正常运行.

后者完全符合一个令人烦恼的例外的定义:它是一个完全非特殊情况下抛出的异常,所以我必须抓住它才能恢复正常的控制流程.幸运的是,它很容易捕获,对吧?只需添加catch (AggregateException)- 哦等等,这是在发生致命错误时被抛出的相同类型.

我需要在返回之前等待任务完成运行(我需要知道他们不再使用他们的数据库连接,文件句柄或其他任何东西),所以我确实需要WaitAll或类似的东西.如果任何任务出现故障,我确实希望这些异常作为未处理的异常传播.我只是不想要取消的例外.

如何防止WaitAll为已取消的任务抛出异常?

exception-handling task-parallel-library cancellation

23
推荐指数
1
解决办法
6216
查看次数

为什么LogicalCallContext无法与异步一起使用?

在这个问题中,Stephen Cleary接受的答案是LogicalCallContext无法正常使用异步.他还在这个 MSDN主题中发布了它.

LogicalCallContext保存一个Hashtable,存储发送到CallContext.LogicalGet/SetData的数据.它只是这个Hashtable的浅层副本.因此,如果您在其中存储可变对象,则不同的任务/线程将看到彼此的更改.这就是Stephen Cleary的示例NDC程序(在MSDN线程上发布)无法正常工作的原因.

但是AFAICS,如果你只在Hashtable中存储不可变数据(可能通过使用不可变集合),那应该有效,让我们实现一个NDC.

然而,Stephen Cleary也在接受的答案中说:

CallContext不能用于此.Microsoft特别建议不要使用CallContext进行远程处理以外的任何操作.更重要的是,逻辑CallContext不了解异步方法如何早期返回并稍后恢复.

不幸的是,该建议的链接已关闭(找不到页面).所以我的问题是,为什么不推荐这个?为什么我不能以这种方式使用LogicalCallContext?说它不理解异步方法是什么意思?从调用者的POV,他们只是返回任务的方法,不是吗?

ETA:另见其他问题.在那里,Stephen Cleary的答案说:

你可以使用CallContext.LogicalSetData和CallContext.LogicalGetData,但我建议你不要,因为当你使用简单的并行性时它们不支持任何类型的"克隆"

这似乎支持我的情况.所以我应该能够建立一个NDC,这实际上是我需要的,而不是log4net.

我写了一些示例代码,它似乎工作,但仅仅测试并不总是捕获并发错误.所以,由于其他帖子中有提示这可能不起作用,我仍然会问:这种方法有效吗?

ETA:当我从下面的答案中运行斯蒂芬提出的复制品时,我没有得到错误的答案,他说我会,我得到正确的答案.即使他说"这里的LogicalCallContext值总是"1"",我总是得到0的正确值.这可能是因为竞争条件?无论如何,我还没有在我自己的电脑上复制任何实际问题.这是我正在运行的确切代码; 它只在这里打印"真实",斯蒂芬说至少在某些时候应该打印"假".

private static string key2 = "key2";
private static int Storage2 { 
    get { return (int) CallContext.LogicalGetData(key2); } 
    set { CallContext.LogicalSetData(key2, value);} 
}

private static async Task ParentAsync() {
  //Storage = new Stored(0); // Set LogicalCallContext value to "0".
  Storage2 = 0;

  Task childTaskA = ChildAAsync();
  // LogicalCallContext value here is always …
Run Code Online (Sandbox Code Playgroud)

.net c# synchronization task-parallel-library async-await

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

在WinForms上使用async/await访问Task.Run中的UI控件

我在WinForms应用程序中有以下代码,只有一个按钮和一个标签:

using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            await Run();
        }

        private async Task Run()
        {
            await Task.Run(async () => {
                await File.AppendText("temp.dat").WriteAsync("a");
                label1.Text = "test";
            });    
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我正在研究的实际应用程序的简化版本.我的印象是,通过在我使用async/await Task.Run我可以设置label1.Text属性.但是,当运行此代码时,我得到错误,我不在UI线程上,我无法访问该控件.

为什么我无法访问标签控件?

c# winforms task-parallel-library async-await

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