Nan*_*rin 1 c# multithreading winforms
这可能是一个愚蠢的问题,如果这已经在其他地方得到了解答,那么我真的很感激,如果有人可以指出我,因为我的搜索没有发现任何确定的.
简而言之,我的问题是,当我在子线程上的子线程中执行childThread.Join()时,标记为停止childThread似乎阻塞了主线程,所以一切都只是挂起.
由于使用Join而阻止用户界面本身并不是问题,因为childThread应该在被告知要退出之后不到一秒钟内完成.
这种情况发生在我正在等待运行重复进程的线程退出之前,我可以运行另一个方法,该方法返回一些信息但不能与另一个进程同时运行.
我的Winforms应用程序通过为硬件设置C API来集成一块USB硬件.
硬件API有一个方法,它将启动一个无限期重复运行的进程,并使用新信息快速回调,然后我需要将这些信息传递给UI.
可以通过另一次调用硬件API来取消此操作,硬件API设置硬件可以看到的标志,以便它知道退出.
我用自己的C#代码包装了这个C API,在包装器中我必须在另一个线程中分离出启动进程调用,这样活动就不会阻塞UI.
以下是我正在做的大致编辑的亮点.
public class DeviceWrapper
{
Thread childThread = null;
void DeviceWrapper
{
//Set the callback to be used by the StartGettingInformation() process
PInvokeMethods.SetGetInformationCallback(InformationAcquiredCallback);
}
public void StartProcess()
{
childThread = new Thread(new ThreadStart(GetInformationProcess))
childThread.Start();
}
void GetInformationProcess()
{
PInvokeMethods.StartGettingInformation();
}
//This callback occurs inside the childThread
void InformationAcquiredCallback(Status status, IntPtr information)
{
//This callback is triggered when anything happens in the
//StartGettingInformation() method, such as when the information
//is ready to be retrieved, or when the process has been cancelled.
if(status == Status.InformationAcquired)
{
FireUpdateUIEvent();
}
//If the cancel flag has been set to true this will be hit.
else if(status == Status.Cancelled)
{
//Reset the cancel flag so the next operation works ok
PInvokeMethods.SetCancelFlag(false);
childThread.Abort();
}
}
//This method runs once, and can't run at the same time as GetInformationProcess
public string GetSpecificInformation()
{
//This triggers InformationAcquiredCallback with a status of Cancelled
StopProcess();
if(childThread.IsAlive)
{
childThread.Join();
}
return PInvokeMethods.GetSpecificInformation();
}
public void StopProcess()
{
PInvokeMethods.SetCancelFlag(true);
}
}
Run Code Online (Sandbox Code Playgroud)
当我调用childThread.Join()时使用这段代码整个应用程序停止运行(我期望用户界面,这很好),而且childThread也似乎停止了,因为回调永远不会再被击中.
但是,如果我使用以下代码:
public string GetSpecificInformation()
{
//This triggers InformationAcquiredCallback with a status of Cancelled
StopProcess();
string s = "";
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
if(childThread.IsAlive)
{
childThread.Join();
}
s = PInvokeMethods.GetSpecificInformation();
}));
return s;
}
Run Code Online (Sandbox Code Playgroud)
然后一切都按预期命中并且childThread完成并且一切都很好,除了显然我的字符串在WaitCallback触发并分配给它之前返回为空.
那么,我是否只需要修改它并更改类,以便我使用QueueUserWorkItem和WaitCallback并触发事件来处理我的字符串返回?
在我的第一个方法中是否有一些愚蠢的行为导致childThread也被阻止了?
或者是否有我应该使用的另一种策略或类,记住它是.NET 3.5我在上面?
嗯,FireUpdateUIEvent(); 听起来可能的方法后发送到MsgQueue( Control.Invoke()).当主线程正在等待时,Join()你就会遇到经典的死锁.
另外,childThread.Abort()不被认为是安全的.
那么,我是否只需要修改它并更改类,以便我使用QueueUserWorkItem和WaitCallback并触发事件来处理我的字符串返回?
我当然会重新设计它.它可能可以简化一点.