当任务列表上的任何()退出程序时

时间:2015-02-02 18:23:12

标签: c# .net multithreading task-parallel-library async-await

我有一个控制台应用程序,我正在使用TPL,当我点击任务时,它会退出..我是线程新手,有人可以指导我正确的方向(我已经单独执行RunJob,它没有例外)。 。所以我不确定如何从这里调试。

以下是代码:

// Program.cs
static void Main(string[] args)
{
    TaskHelper helper = new TaskHelper();
    helper.StartProcessing();
}

// TaskHelper Class
public async void StartProcessing()
{
    var tasks = new List<Task<bool>>();
    int taskNum = _queueList.Count < maxThreads ? _queueList.Count : maxThreads;
    for (int i = 0; i < taskNum; i++)
    {
        UCMDo doObj;
        if (_taskQueue.TryDequeue(out doObj))
        {
            tasks.Add(RunOps(doObj));
        }
    }

    while (tasks.Count > 0)
    {
        try
        {
            // Program exits here when its hitting WhenAny line
            var t = await Task.WhenAny(tasks);
            tasks.Remove(t);
            await t;
        }
        catch (OperationCanceledException)
        {
        }
        catch (Exception exc) { }
        finally
        {
           // add to tasks, and RunOps
        }
    }
}

async Task<bool> RunOps(UCMDo doJ)
{
    var result = await Task.Run(() => UCMFactory.RunJob(_job, doJ));
    return result;
}

1 个答案:

答案 0 :(得分:4)

如果您在没有等待的情况下致电StartProcessing,那么会发生什么情况(您不能async void),因此程序到达Main的结尾StartProcessing中的操作仍在运行时结束。

StartProcessing应该返回一个任务,您应该等待该任务完成。这通常是通过等待任务来完成的(即await helper.StartProcessing()),但由于您无法在await中使用Main,因此您应该同步执行此操作(尽管这是唯一的可以接受的地方:

static void Main(string[] args)
{
    TaskHelper helper = new TaskHelper();
    helper.StartProcessingAsync().Wait();
}

正如Servy正确指出的那样,一个更强大且生产就绪的解决方案将使用某种消息循环。一个例子是Stephen Cleary's AsyncContext

static void Main(string[] args)
{
    TaskHelper helper = new TaskHelper();
    AsyncContext.Run(() => helper.StartProcessingAsync());
}

注意:

    不应在UI事件处理程序之外使用
  • async void
  • async方法通常应命名为XAsync(即StartProcessingAsync