C# 调用不切换回单独的线程

C# 调用不切换回单独的线程,c#,multithreading,invoke,C#,Multithreading,Invoke,我有下面的方法,它运行在与主UI线程不同的单独线程上,我正在尝试更新主线程上的ListBox控件。代码确实起作用,字段也得到更新,但当Invoke方法运行时,它会切换到主线程。问题是调用后的代码也在主线程上运行,但我需要它在单独的线程上运行 public static void Status_Message(string str, int destination, int prompt) { //Clear_System_Message_Area();

我有下面的方法,它运行在与主UI线程不同的单独线程上,我正在尝试更新主线程上的ListBox控件。代码确实起作用,字段也得到更新,但当Invoke方法运行时,它会切换到主线程。问题是调用后的代码也在主线程上运行,但我需要它在单独的线程上运行

    public static void Status_Message(string str, int destination, int prompt)
    {
        //Clear_System_Message_Area();

        sysmsg++;
        ListBox tl = Application.OpenForms["GMLEC"].Controls["groupBox2"].Controls["TestList"] as ListBox;
        if (!tl.InvokeRequired)
        {
            tl.Items.Add(str);
            tl.Refresh();
        }
        else
        {
            tl.Invoke(new Action<string, int, int>(Status_Message), str, destination, prompt);
        }

        if (destination == 1)
        {
            Printer.Output(str);
        }

        if (prompt == 1)
        {
            Pause(false);
        }

        if (sysmsg > 23)
        {
            Pause(true);
        }
    }
有没有办法让它返回到单独的线程?

这可能会有帮助

通常,我使用Invoke在一段时间后激活脚本的一部分。Invoke不重复,如果希望重复,可以使用InvokeRepeating

另一种选择是使用多线程。以下是如何使用多线程:

using System.Threading

public static Thread newThread = new Thread(MultiThread)

private void Start()
{
newThread.Start()
//also newThread.Abort() to quit the thread
}

private static void MultiThread()
{
    // this is the seporate thread
    // i normally use this for a "while (True)" loop cause it will stop responding 
    //otherwise

}

检查是否有打字错误


如果您不希望代码在UI线程上运行,请不要调用包含它的方法,希望这会有所帮助

无论如何,我不同意任何使用InvokeRequired的代码。首先,您应该从上下文中知道是否需要调用。如果您不知道正在执行的代码在哪个线程上,那么UI和代码的后台任务部分之间存在太多耦合

但是第二,Control.Invoke方法必须检查哪个线程是当前线程,因为无论您是否在UI线程上,它都必须工作。您总是可以从UI线程安全地调用它,当您这样做时,它不能将您的委托排队等待调用,因为这样会死锁。它必须直接调用委托,但只有在这种情况下,这意味着它无论如何都在执行invokererequired检查

因此,考虑到所有这些因素,只需编写代码,以便始终调用需要调用的部分,并完成它

例如:

公共静态无效状态\u Messagestring str,int destination,int提示符 { //清除系统信息区域; sysmsg++; ListBox tl=Application.OpenForms[GMLEC]。控件[groupBox2]。控件[TestList]作为ListBox; tl.InvokeMethodInvoker=> { tl.Items.Addstr; tl.刷新; }; 如果目的地==1 { 打印机输出str; } 如果提示==1 { 波塞法尔斯; } 如果sysmsg>23 { 波塞特鲁; } } 现在,关于这一点,还有一些其他注意事项:

你是否应该打电话给Refresh是值得怀疑的。让Winforms自己处理更新。如果您以某种方式干扰了正常刷新窗口,请修复该问题。不要叫自己刷新来绕圈子。 几乎可以肯定的是,封装ListBox对象的方法比总是从UI控制图的顶部查找更好。例如,可能实际对象应该直接引用,例如从TestList字段引用,并传递给最终需要它的代码。 最后,也是最重要的一点,在现代代码中,使用Invoke是一个很大的警告标志。您的整个代码很有可能被重构为使用async/await,使其能够更自然地读取并仍能正常工作,但至少最好使用Progress来调解这样的跨线程更新。
解决这些问题超出了当前问题的范围,但我鼓励您考虑下面的建议。

简单,不要调用整个函数,只调用您需要调用的函数。我还认为,每个同步调用的人都应该在同行的陪审团面前为自己的选择辩护,他们必须一致同意,或者他们需要修复自己的代码。你怎么知道tl.Invoke行之前的代码在后台线程上运行,在这行之后它在主UI线程上运行?我没有看到要记录的Thread.CurrentThread.ManagedThreadId。