C# 我可以启动一个线程并使用调度程序来安排它的工作吗?

Ant*_*nyM 4 c# multithreading dispatcher

我想要一个可以安排工作的专用线程。我可以使用dispatcher.invoke来做到这一点还是我必须做一些自定义的事情?

看起来调度程序应该可以工作,但我不知道如何实际让线程开始处理调度程序的工作。

The*_*ias 5

我看到的唯一问题是如何判断线程的调度程序何时启动并运行,并准备好接受命令。Thread.Sleep(100)为此我添加了一个。没有它 aTaskCanceledException就会被抛出。

Thread.CurrentThread.Name = "Main";
var thread = new Thread(() =>
{
    Console.WriteLine($"{Thread.CurrentThread.Name} Started");
    Dispatcher.Run();
    Console.WriteLine($"{Thread.CurrentThread.Name} Finished");
});
thread.IsBackground = true;
thread.Name = "Worker";
thread.Start();
Thread.Sleep(100);
Dispatcher dispatcher = Dispatcher.FromThread(thread);
dispatcher.Invoke(() =>
{
    Console.WriteLine($"Processed by {Thread.CurrentThread.Name}");
});
dispatcher.InvokeShutdown();
thread.Join();
Run Code Online (Sandbox Code Playgroud)

输出:

工人开始
由工人处理
工人完成


更新:可以使用BlockingCollection. 下面的类有许多缺失的功能(取消、超时、参数、处置等),但提供了可以由多个工作线程共享的重要优势。

public class CustomDispatcher
{
    private readonly BlockingCollection<(Action Action,
        TaskCompletionSource<bool> TCS)> _blockingCollection =
        new BlockingCollection<(Action, TaskCompletionSource<bool>)>();

    public void Run()
    {
        foreach (var item in _blockingCollection.GetConsumingEnumerable())
        {
            try
            {
                item.Action.Invoke();
                item.TCS.SetResult(true);
            }
            catch (Exception ex)
            {
                item.TCS.TrySetException(ex);
            }
        }
    }

    public Task InvokeAsync(Action action)
    {
        var tcs = new TaskCompletionSource<bool>();
        _blockingCollection.Add((action, tcs));
        return tcs.Task;
    }

    public void Invoke(Action action) => InvokeAsync(action).Wait();

    public void InvokeShutdown() => _blockingCollection.CompleteAdding();
}
Run Code Online (Sandbox Code Playgroud)

更新:关于内置,可以使用 a 进行精确控制,Dispatcher而不是使用混乱的方式Thread.Sleep(100)给调度程序启动时间:TaskCompletionSource<Dispatcher>

Thread.CurrentThread.Name = "Main";
var dispatcherReady = new TaskCompletionSource<Dispatcher>();
var thread = new Thread(() =>
{
    Console.WriteLine($"{Thread.CurrentThread.Name} Started");
    dispatcherReady.SetResult(Dispatcher.CurrentDispatcher);
    Dispatcher.Run();
    Console.WriteLine($"{Thread.CurrentThread.Name} Finished");
});
thread.IsBackground = true;
thread.Name = "Worker";
thread.Start();
var dispatcher = dispatcherReady.Task.Result;
dispatcher.Invoke(() =>
{
    Console.WriteLine($"Processed by {Thread.CurrentThread.Name}");
});
dispatcher.InvokeShutdown();
thread.Join();
Run Code Online (Sandbox Code Playgroud)

输出:

工人开始
由工人处理
工人完成