Whenany() 在任务列表中退出程序

Whenany() on task list is exiting the program

我有一个控制台应用程序,我在其中使用 TPL,当我在任务中点击 whenany 时它会退出。我是线程的新手,有人可以指导我正确的方向吗(我单独执行了 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;
}

发生的事情是你调用 StartProcessing 而不等待它(你不能,因为它是 async void)所以程序到达 Main 的末尾并在操作时结束在 StartProcessing 中仍然是 运行.

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

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

备注:

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