Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#我可以启动一个线程并使用调度程序来安排它的工作吗?_C#_Multithreading_Dispatcher - Fatal编程技术网

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

C#我可以启动一个线程并使用调度程序来安排它的工作吗?,c#,multithreading,dispatcher,C#,Multithreading,Dispatcher,我想有一个专门的线程,我可以安排工作。我可以使用dispatcher.invoke执行此操作,还是必须执行自定义操作 看起来dispatcher应该可以工作,但我不知道如何让线程从dispatcher开始处理工作 我猜您正在使用C#和UWP或类似的东西 您不能(或者至少不容易)保留线程并向其分派任务。在当前Windows环境中,任务在同步上下文上运行。实际上,这意味着一组线程,(a)在UI同步上下文中,线程集仅包含一个UI线程,或者(b)在线程池同步上下文中,存在工作线程的集合 public c

我想有一个专门的线程,我可以安排工作。我可以使用dispatcher.invoke执行此操作,还是必须执行自定义操作


看起来dispatcher应该可以工作,但我不知道如何让线程从dispatcher开始处理工作

我猜您正在使用C#和UWP或类似的东西

您不能(或者至少不容易)保留线程并向其分派任务。在当前Windows环境中,任务在同步上下文上运行。实际上,这意味着一组线程,(a)在UI同步上下文中,线程集仅包含一个UI线程,或者(b)在线程池同步上下文中,存在工作线程的集合

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();
}
在大多数情况下,如果您试图执行CPU密集型工作,那么您应该在线程池中运行它,您可以通过调用
Task.Run(asyncAction)
来执行此操作。要将结果返回到UI,必须使用
Dispatcher.RunAsync
。如果希望先从方法返回,然后在UI线程中执行某些操作,也可以从UI线程使用dispatcher


您不应该使用Dispatcher来安排后台工作。使用Dispatcher计划的所有工作都将在单个UI线程上运行,从而导致它陷入停滞

我猜您正在使用C#和UWP或类似的东西

您不能(或者至少不容易)保留线程并向其分派任务。在当前Windows环境中,任务在同步上下文上运行。实际上,这意味着一组线程,(a)在UI同步上下文中,线程集仅包含一个UI线程,或者(b)在线程池同步上下文中,存在工作线程的集合

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();
}
在大多数情况下,如果您试图执行CPU密集型工作,那么您应该在线程池中运行它,您可以通过调用
Task.Run(asyncAction)
来执行此操作。要将结果返回到UI,必须使用
Dispatcher.RunAsync
。如果希望先从方法返回,然后在UI线程中执行某些操作,也可以从UI线程使用dispatcher

您不应该使用Dispatcher来安排后台工作。使用Dispatcher计划的所有工作都将在单个UI线程上运行,从而导致它陷入停滞

打电话。这将阻塞线程,调度器将运行无休止的循环,等待消息并处理它们

在执行此操作之前,最好将dispatcher实例存储在某个位置,其他线程可以在该位置访问它以发布消息或关闭

缺点是,您只需使用dispatcher来发布该线程的工作。它不会做任何其他事情。调用InvokeShutdown停止。

调用。这将阻塞线程,调度器将运行无休止的循环,等待消息并处理它们

在执行此操作之前,最好将dispatcher实例存储在某个位置,其他线程可以在该位置访问它以发布消息或关闭


缺点是,您只需使用dispatcher来发布该线程的工作。它不会做任何其他事情。调用InvokeShutdown停止。

我看到的唯一问题是如何判断线程的调度程序何时启动并运行,以及何时准备接受命令。为此,我添加了一个
线程。Sleep(100)
。如果没有它,将抛出一个
TaskCanceledException

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();
输出:

工人已启动
由工人处理
工人完成


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

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

工人已启动
由工人处理
工人完成


我看到的唯一问题是如何判断线程的调度程序何时启动并运行,以及何时准备接受命令。为此,我添加了一个
线程。Sleep(100)
。如果没有它,将抛出一个
TaskCanceledException

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();
输出:

工人已启动
由工人处理
工人完成


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

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

工人已启动
由工人处理
工人完成