这可能是一个愚蠢的问题,如果已经在其他地方回答了这个问题,那么如果有人可以指出我的想法,因为我的搜索没有确定性,我将非常感激。
简而言之,我的问题是,当我在已标记为停止childThread的子线程上的UI线程中执行childThread.Join()时,它似乎与主线程一样阻塞,因此一切都挂起了。
由于使用Join会导致UI阻塞本身并不是一个问题,因为childThread应该在被告知退出后不到一秒钟的时间内完成。
这是在我等待运行重复进程的线程退出之前发生的,然后我才能运行另一个返回一些信息但不能与另一个进程同时运行的方法。
我的Winforms应用程序通过修改硬件的C API来与USB硬件集成。
硬件API有一种方法,该方法将启动一个进程,该进程将无限期地重复运行并快速回调新信息,然后我需要将其传递给UI。
可以通过再次调用硬件API来取消此操作,该调用将设置硬件可以看到的标志,以便知道退出。
我已经用自己的C#代码包装了这个C API,并且在包装器中,我不得不在另一个线程中启动启动过程调用,以使 Activity 不会阻塞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);
}
}
当我调用childThread.Join()时,使用此代码会使整个应用程序停止运行(我希望UI可以停下来,这很好),并且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;
}
然后一切都按预期方式命中,并且childThread确实完成并且一切正常,除了显然我的字符串在WaitCallback触发并分配给它之前被返回为空。
因此,我是否只需要吸收它并更改类,以便使用QueueUserWorkItem和WaitCallback并触发一个事件来处理我的字符串返回?
我在第一种方法中正在执行某些愚蠢的操作,该操作也导致childThread也阻塞了吗?
还是考虑到我使用的是.NET 3.5,我是否应该完全使用另一种策略或类(class)?
最佳答案
好吧,FireUpdateUIEvent();
听起来像一种方法,可能会将Post Post发送到MsgQueue(Control.Invoke()
)。当主线程在Join()
中等待时,您将遇到经典的死锁。
此外,childThread.Abort()
不被认为是安全的。
我当然会重新设计它。可能可以简化一点。