这可能是一个愚蠢的问题,如果这已经在其他地方得到了答案,那么如果有人能指出我,我会非常感激,因为我的搜索没有发现任何确定的东西。
简而言之,我的问题是,当我在子线程上的子线程中执行childThread.Join()时,标记为停止childThread的子线程似乎阻塞了主线程,所以一切都只是挂起。登记/>
因为使用Join而阻止用户界面本身并不是一个问题,因为childThread应该在被告知要退出之后不到一秒钟完成。
这种情况发生在我正在等待运行重复进程的线程退出之前,我可以运行另一个方法,该方法返回一些信息但不能与另一个进程同时运行。
My Winforms应用程序通过为硬件设置C API来集成一块USB硬件。
硬件API有一个方法可以启动一个无限期重复运行的进程,并使用新信息快速回调,然后我需要将这些信息传递给用户界面。
可以通过另一次调用硬件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);
}
}
当我调用childThread.Join()时使用这段代码,整个应用程序会停止(我期望用户界面,这很好),而且childThread也似乎停止了,因为回调永远不会再次被击中。 / p>
但是,如果我改为使用以下代码:
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我在吗?
答案 0 :(得分:5)
好吧,FireUpdateUIEvent();
听起来像是一种可能发布发送到MsgQueue(Control.Invoke()
)的方法。当主线程在Join()
中等待时,您就会遇到经典的死锁。
此外,childThread.Abort()
不被视为安全。
那么,我是否只需要修改它并更改类,以便我使用QueueUserWorkItem和WaitCallback并触发事件来处理我的字符串返回?
我当然会重新设计它。它可能可以简化一点。