代码之家  ›  专栏  ›  技术社区  ›  TK.

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

  •  0
  • TK.  · 技术社区  · 16 年前

    如果我有线程A,它是主应用程序线程和辅助线程。如何检查函数是否在线程B中被调用?

    基本上,我尝试实现以下代码截图:

    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

    我意识到我看待这个问题的方式是错误的(感谢下面的答案,是谁帮助我看到了这一点),我关心的是IO不会发生在threada上。这意味着它可能发生在破旧的或任何其他线程上,例如后台工作人员。我已经决定在上述f语句的其他部分中创建一个新的后台工作人员,以确保以非阻塞方式执行IO。我不完全确定这是解决我的问题的最佳方案,但它似乎是有效的!

    4 回复  |  直到 16 年前
        1
  •  5
  •   Justin Grant    16 年前

    有一种方法可以做到:

    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 .

    如果控制台或通用服务器应用程序(没有图形用户界面),您需要弄清楚如何让主线程知道它正在等待工作——您可能需要考虑一个备用的实现,该实现有一个I/O工作线程或线程池,该线程池刚好位于执行您排队等待的I/O请求的周围。或者,您可能想考虑同步I/O请求(更容易),而不是将调用编组到一个线程(更难)。

    如果是ASP.NET,则可能是以错误的方式实现了这一点。通常,使用ASP.NET异步页和/或使用 lock{} 或其他同步方法。

        2
  •  1
  •   Guffa    16 年前

    你想做的与 InvokeRequired Windows窗体控件的属性可以,因此如果它是Windows窗体应用程序,则可以只使用主窗体的属性:

    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
  •   Henk Holterman    16 年前

    在threadb上调用performio这段代码的另一部分只能在threadb是运行messageloop的主线程时工作。

    所以也许你应该重新考虑一下你在这里做什么,这不是一个正常的建筑。

        4
  •  1
  •   Matt Davis    16 年前

    你的第二个线程除了 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 财产。这将有助于您在调试会话中查看线程窗口,如果线程标识有疑问,它还允许您将线程名称打印到控制台或输出窗口。