如何检查特定线程上是否正在调用函数?

时间:2009-11-16 13:15:31

标签: c# multithreading

如果我有线程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。我不完全确定这是我问题的最佳解决方案,但它似乎有效!

4 个答案:

答案 0 :(得分:5)

这是一种方法:

if (System.Threading.Thread.CurrentThread.ManagedThreadId == ThreadB.ManagedThreadId) 
            ...

我对.NET的Thread类实现知之甚少,不知道上面的比较是否等同于Equals(),但是如果没有这方面的知识,比较ID是一个安全的选择

可能有更好的方法(更好,更快,更快等)来完成你想要做的事情,具体取决于以下几点:

  • 你在构建什么样的应用程序(ASP.NET,WinForms,控制台等)?
  • 您为什么只想在一个线程上强制执行I / O?
  • 这是什么类型的I / O? (例如写入一个文件?网络I / O约束到一个套接字等等)
  • 相对于锁定成本,并发工作线程数等,您的性能限制是什么?
  • 代码中的“else”子句是否需要阻止,即发即弃或更复杂
  • 你想如何处理超时,死锁等等。

将此信息添加到您的问题中会很有帮助,但如果您使用的是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窗口。