如果我有线程A,它是主要的应用程序线程和辅助线程。如何检查线程B中是否正在调用函数?
基本上我正在尝试实现以下代码snippit:
public void ensureRunningOnCorrectThread()
{
if( function is being called within ThreadB )
{
performIO()
}
else
{
// call performIO so that it is called (invoked?) on ThreadB
}
}
有没有办法在C#中执行此功能,还是有更好的方法来查看问题?
编辑1
我已经注意到MSDN文档中的以下内容,虽然我怀疑它是否是一件好事! :
// if function is being called within ThreadB
if( System.Threading.Thread.CurrentThread.Equals(ThreadB) )
{
}
编辑2
我意识到我以错误的方式看待这个问题(感谢下面的答案让我看到了这一点)我所关心的只是在ThreadA上没有发生IO。这意味着它可能发生在ThreadB或任何其他线程上,例如一个BackgroundWorker。我已经决定在上面的f语句的else部分中创建一个新的BackgroundWorker,以确保以非阻塞的方式执行IO。我不完全确定这是我问题的最佳解决方案,但它似乎有效!
答案 0 :(得分:5)
这是一种方法:
if (System.Threading.Thread.CurrentThread.ManagedThreadId == ThreadB.ManagedThreadId)
...
我对.NET的Thread
类实现知之甚少,不知道上面的比较是否等同于Equals()
,但是如果没有这方面的知识,比较ID是一个安全的选择
可能有更好的方法(更好,更快,更快等)来完成你想要做的事情,具体取决于以下几点:
将此信息添加到您的问题中会很有帮助,但如果您使用的是WinForms应用程序并且您正在讨论面向用户的GUI I / O,则可以跳过其他问题,因为该方案很明显。
请记住,// call performIO so that it is called (invoked?) on ThreadB
实现将根据WinForms,ASP.NET,控制台等而有所不同。
如果是WinForms,请查看this CodeProject post以获得一种很酷的处理方式。另请参阅MSDN,了解如何使用InvokeRequired处理此问题。
如果是Console或通用服务器应用程序(无GUI),您需要弄清楚如何让主线程知道它有等待工作 - 您可能需要考虑具有I / O的备用实现工作线程或线程池,它只是围绕执行排队到它的排队I / O请求。或者你可能想要考虑同步你的I / O请求(更容易),而不是将调用调用到一个线程(更难)。
如果是ASP.NET,你可能会以错误的方式实现它。使用ASP.NET异步页面和/或(按上述方式)使用lock{}
或其他同步方法将I / O同步到您的I / O通常更有效。
答案 1 :(得分:1)
你的代码片段的else部分,在ThreadB上调用PerformIO只有在ThreadB是运行Messageloop的主线程时才能工作。
所以也许你应该重新考虑一下你在这里做什么,这不是一个正常的结构。
答案 2 :(得分:1)
您要做的是与窗体控件的InvokeRequired
属性相反,所以如果它是窗体应用程序,您可以只使用主窗体的属性:
if (InvokeRequired) {
// running in a separate thread
} else {
// running in the main thread, so needs to send the task to the worker thread
}
答案 3 :(得分:1)
除了performIO()
函数之外,您的辅助线程是否还执行其他操作?如果没有,那么一个简单的方法是使用System.Threading.ManualResetEvent
。让辅助线程坐在while循环中等待设置事件。发出事件信号时,辅助线程可以执行I / O处理。要发出事件信号,请让主线程调用事件对象的Set()方法。
using System.Threading;
static void Main(string[] args)
{
ManualResetEvent processEvent = new ManualResetEvent(false);
Thread thread = new Thread(delegate() {
while (processEvent.WaitOne()) {
performIO();
processEvent.Reset(); // reset for next pass...
}
});
thread.Name = "I/O Processing Thread"; // name the thread
thread.Start();
// Do GUI stuff...
// When time to perform the IO processing, signal the event.
processEvent.Set();
}
另外,除此之外,养成在创建任何System.Threading.Thread对象时命名的习惯。创建辅助线程时,请通过Name属性设置线程名称。这将在查看Debug会话中的Threads窗口时帮助您,并且如果线程标识有疑问,它还允许您将线程名称打印到控制台或Output窗口。