运行 C# 中同一异步线程中的不同任务
Run different task in same asynchronous thread in C#
我不得不问,因为我找不到与 UI BeginInvoke 异步完成相同的方法。
我在 Winforms 上的示例程序 运行ning 和所有委托方法都在主 UI 线程中调用。我已记录状态并在不同 BeginInvoke
.
的同一线程上找到它 运行
从 Winforms 登录 UI:
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
我想将其转换为 class 库以作为 DLL 集成到我的实际应用程序中。但是我找不到如何在同一线程中将 fnCmdInProgressAction
和 SendNextCommand
方法设为 运行。因为,我有一个链命令,它需要排队,因为对象值将被清除并允许下一个命令执行到串口。
从我的 class 库中登录:
13/01/2021 11:30:51 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 6
13/01/2021 11:30:52 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 9
13/01/2021 11:30:55 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:55 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 6
13/01/2021 11:30:56 [SendNextCommand] - [SendNextCommand] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:56 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 9
13/01/2021 11:30:57 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:58 [SendNextCommand] - [SendNextCommand] Background: True, Thread Pool: True, Thread ID: 6
我试过线程池,Delegate.BeginInvoke,线程任务。但仍然导致不同的线程。以下是我尝试过的示例:
private delegate void CmdInProgressAction(bool state, Tools.CommandReply cr);
private void fnCmdInProgressAction(object param)
{
if (cr != null)
{
m_CmdInProgress = cr;
//.......
}
m_CmdInProgress = null;
}
// Code from Winform UI BeginInvoke
private void SetCmdInProgress(bool state, CommandReply cr)
{
CmdInProgressAction fn = null;
object[] param = new object[] { state, cr };
fn = new CmdInProgressAction(fnCmdInProgressAction);
BeginInvoke(fn, param);
}
// My try
private void SetCmdInProgress(bool state, CommandReply cr)
{
//========================= TRY 1 =================================================
new Task(() => { fnCmdInProgressAction(state, cr); }).Start();
//========================= TRY 2 =================================================
CmdInProgressAction fn = fnCmdInProgressAction;
fn.BeginInvoke(state, cr, null, null);
//========================= TRY 3 =================================================
new Thread(new ThreadStart(() => fnCmdInProgressAction(state, cr))).Start();
//========================= TRY 4 =================================================
ThreadPool.QueueUserWorkItem(fnCmdInProgressAction, new object[] { state, cr });
}
public void SendNextCommand(TXNextCommand tnxc)
{
Thread thread = Thread.CurrentThread;
string message = $"[SendNextCommand] Background: {thread.IsBackground}, Thread Pool: {thread.IsThreadPoolThread}, Thread ID: {thread.ManagedThreadId}";
WriteLog.ProcessLog(message);
if (m_CmdInProgress == null)
{
m_CmdInProgress = tnxc.mcr;
serial.SendCommand(m_CmdInProgress);
}
}
private string HandleReply(bool GoodResult, Tools.CommandReply cr)
{
int nextChannel = cr.m_tag + 1;
TXNextCommand tnxc= new TXNextCommand(new TXReadCassetteDeno($"Read Cassette {nextChannel} Deno", "RV-1X2", 5, channel: nextChannel));
tnxc.mcr.SetReplyHandlerDelegate(HandleReply);
/// Below is code from Winforms UI Async on main thread
dSendNextCommand fn = new dSendNextCommand(SendNextCommand);
object[] param = new object[] { nctt };
BeginInvoke(fn, param);
}
运行 在同一线程中 HandleReply
和 fnCmdInProgressAction
的委托的正确方法是什么 SendNextCommand
调用,m_CmdInProgress
是已经为空,因此它可以发送下一个命令。 Winforms UI 没有问题,因为它就像在同一个线程上排队调用。我如何在 class 库上应用它,因为我尝试过的无法达到我想要的效果。我读过任务异步编程,TPL。我不能使用异步,因为它会弄乱串行 class 对象上的委托。
回答我的问题。根据 Peter Csala 的推荐,我正在使用 ConcurrentExclusiveSchedulerPair
。现在命令可以按需要执行。这是我所做的。
static ConcurrentExclusiveSchedulerPair taskSchedulerPair = new ConcurrentExclusiveSchedulerPair();
TaskFactory exclusiveTaskFactory = new TaskFactory(taskSchedulerPair.ExclusiveScheduler);
private void SetCmdInProgress(bool state, Tools.CommandReply cr)
{
//====================================================================================
exclusiveTaskFactory.StartNew(() => { fnCmdInProgressAction(new object[] { state, cr }); });
//====================================================================================
}
private string HandleReply(bool GoodResult, Tools.CommandReply cr)
{
int nextChannel = cr.m_tag + 1;
TXCommand.TXNextCommand tnxc = new TXCommand.TXNextCommand(new TXCommand.TXReadCassetteDeno($"Read Cassette {nextChannel} Deno", "RD/9X27", 5, channel: nextChannel));
tnxc.mcr.SetReplyHandlerDelegate(HandleReply);
//====================================================================================
exclusiveTaskFactory.StartNew(() => { SendNextCommand(new object[] { tnxc }); });
//====================================================================================
}
我还有一些不同的线程id;但是,通过使用 ConcurrentExclusiveSchedulerPair
,它可以在按照所需的流程继续执行另一个任务之前对任务进行排队
我不得不问,因为我找不到与 UI BeginInvoke 异步完成相同的方法。
我在 Winforms 上的示例程序 运行ning 和所有委托方法都在主 UI 线程中调用。我已记录状态并在不同 BeginInvoke
.
从 Winforms 登录 UI:
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:23 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: False, Thread Pool: False, Thread ID: 1
13/01/2021 11:57:24 [SendNextCommand] - [SendNextCommand] Background: False, Thread Pool: False, Thread ID: 1
我想将其转换为 class 库以作为 DLL 集成到我的实际应用程序中。但是我找不到如何在同一线程中将 fnCmdInProgressAction
和 SendNextCommand
方法设为 运行。因为,我有一个链命令,它需要排队,因为对象值将被清除并允许下一个命令执行到串口。
从我的 class 库中登录:
13/01/2021 11:30:51 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 6
13/01/2021 11:30:52 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 9
13/01/2021 11:30:55 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:55 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 6
13/01/2021 11:30:56 [SendNextCommand] - [SendNextCommand] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:56 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 9
13/01/2021 11:30:57 [fnCmdInProgressAction] - [fnCmdInProgressAction] Background: True, Thread Pool: True, Thread ID: 7
13/01/2021 11:30:58 [SendNextCommand] - [SendNextCommand] Background: True, Thread Pool: True, Thread ID: 6
我试过线程池,Delegate.BeginInvoke,线程任务。但仍然导致不同的线程。以下是我尝试过的示例:
private delegate void CmdInProgressAction(bool state, Tools.CommandReply cr);
private void fnCmdInProgressAction(object param)
{
if (cr != null)
{
m_CmdInProgress = cr;
//.......
}
m_CmdInProgress = null;
}
// Code from Winform UI BeginInvoke
private void SetCmdInProgress(bool state, CommandReply cr)
{
CmdInProgressAction fn = null;
object[] param = new object[] { state, cr };
fn = new CmdInProgressAction(fnCmdInProgressAction);
BeginInvoke(fn, param);
}
// My try
private void SetCmdInProgress(bool state, CommandReply cr)
{
//========================= TRY 1 =================================================
new Task(() => { fnCmdInProgressAction(state, cr); }).Start();
//========================= TRY 2 =================================================
CmdInProgressAction fn = fnCmdInProgressAction;
fn.BeginInvoke(state, cr, null, null);
//========================= TRY 3 =================================================
new Thread(new ThreadStart(() => fnCmdInProgressAction(state, cr))).Start();
//========================= TRY 4 =================================================
ThreadPool.QueueUserWorkItem(fnCmdInProgressAction, new object[] { state, cr });
}
public void SendNextCommand(TXNextCommand tnxc)
{
Thread thread = Thread.CurrentThread;
string message = $"[SendNextCommand] Background: {thread.IsBackground}, Thread Pool: {thread.IsThreadPoolThread}, Thread ID: {thread.ManagedThreadId}";
WriteLog.ProcessLog(message);
if (m_CmdInProgress == null)
{
m_CmdInProgress = tnxc.mcr;
serial.SendCommand(m_CmdInProgress);
}
}
private string HandleReply(bool GoodResult, Tools.CommandReply cr)
{
int nextChannel = cr.m_tag + 1;
TXNextCommand tnxc= new TXNextCommand(new TXReadCassetteDeno($"Read Cassette {nextChannel} Deno", "RV-1X2", 5, channel: nextChannel));
tnxc.mcr.SetReplyHandlerDelegate(HandleReply);
/// Below is code from Winforms UI Async on main thread
dSendNextCommand fn = new dSendNextCommand(SendNextCommand);
object[] param = new object[] { nctt };
BeginInvoke(fn, param);
}
运行 在同一线程中 HandleReply
和 fnCmdInProgressAction
的委托的正确方法是什么 SendNextCommand
调用,m_CmdInProgress
是已经为空,因此它可以发送下一个命令。 Winforms UI 没有问题,因为它就像在同一个线程上排队调用。我如何在 class 库上应用它,因为我尝试过的无法达到我想要的效果。我读过任务异步编程,TPL。我不能使用异步,因为它会弄乱串行 class 对象上的委托。
回答我的问题。根据 Peter Csala 的推荐,我正在使用 ConcurrentExclusiveSchedulerPair
。现在命令可以按需要执行。这是我所做的。
static ConcurrentExclusiveSchedulerPair taskSchedulerPair = new ConcurrentExclusiveSchedulerPair();
TaskFactory exclusiveTaskFactory = new TaskFactory(taskSchedulerPair.ExclusiveScheduler);
private void SetCmdInProgress(bool state, Tools.CommandReply cr)
{
//====================================================================================
exclusiveTaskFactory.StartNew(() => { fnCmdInProgressAction(new object[] { state, cr }); });
//====================================================================================
}
private string HandleReply(bool GoodResult, Tools.CommandReply cr)
{
int nextChannel = cr.m_tag + 1;
TXCommand.TXNextCommand tnxc = new TXCommand.TXNextCommand(new TXCommand.TXReadCassetteDeno($"Read Cassette {nextChannel} Deno", "RD/9X27", 5, channel: nextChannel));
tnxc.mcr.SetReplyHandlerDelegate(HandleReply);
//====================================================================================
exclusiveTaskFactory.StartNew(() => { SendNextCommand(new object[] { tnxc }); });
//====================================================================================
}
我还有一些不同的线程id;但是,通过使用 ConcurrentExclusiveSchedulerPair
,它可以在按照所需的流程继续执行另一个任务之前对任务进行排队