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