【问题标题】:Why Invoke is needed?为什么需要调用?
【发布时间】:2015-07-08 22:37:49
【问题描述】:

我有点理解线程和调用的意义,但不是很好。我正在使用教程制作服务器/客户端应用程序。现在我有2个功能。在断开连接功能中我需要调用,但在接收功能中我不需要。

为什么会这样(问题是 lstClient)?

如果我在 Received 函数中有 Invoke,那么 Invoke 只是出于某种原因循环,为什么?

void client_Disconnected(Client sender)
{
    Invoke((MethodInvoker)delegate
    {
        for (int i = 0; i < lstClient.Items.Count; i++)
        {
            Client client = lstClient.Items[i].Tag as Client;
            if(client.ID == sender.ID)
            {
                lb_ID.Items.RemoveAt(i); lb_ip.Items.RemoveAt(i); lb_users.Items.RemoveAt(i);
                lstClient.Items.RemoveAt(i);
                break;
            }
        }
    });
}

void client_Received(Client sender, byte[] data)
{
    /*Invoke((MethodInvoker)delegate
    {*/
        for (int i = 0; i < lstClient.Items.Count; i++)
        {
            Client client = lstClient.Items[i].Tag as Client;
            if (client.ID == sender.ID)
            {
                if (Encoding.Default.GetString(data) == "end") 
                {
                    client_Disconnected(client); 
                    break;
                }
                lstClient.Items[i].SubItems[2].Text = Encoding.Default.GetString(data);
                lstClient.Items[i].SubItems[3].Text = DateTime.Now.ToString() ;
                break;
            }
        }
    //});
}

【问题讨论】:

  • 方法是否在主线程上执行是一个问题。我不知道你是如何使用这些方法和你的代码逻辑的,但是 sn-p 表明 Received 在 UI 线程上运行,而 DCed 在另一个线程上运行(我并不是说这是有道理的)。无论如何,由于涉及 UI 业务(来自不同线程),因此需要 Invoke,因此如果您有不同的逻辑,您可能不需要在其中任何一种方法中使用 Invoke。
  • @YoryeNathan 关于线程,我怎么知道什么时候在主线程上运行,什么时候没有?这是什么时候发生的,是代码中的东西还是它是如何工作的?
  • 代码本身表明了运行的线程。如果你很懒,你可以在方法中设置一个断点,然后在 Debug 中打开 Threads 选项卡,看看你在哪里。

标签: c# multithreading invoke


【解决方案1】:

这完全取决于方法的调用方式。

在某些对象(控件)上有一个属性 InvokeRequired 属性,可用于在需要时选择性地调用。

在 WinForms 应用程序中,任何更改表单的方法都必须在 Form UI 线程中运行以避免冲突,但是任何不进行更改的方法通常可以在不调用的情况下安全地调用,但它可能会得到部分结果。

【讨论】:

  • 将 UI 线程称为“表单主线程”可能有点误导。我感觉每个表单都可能有自己的主线程。最好只说“UI 线程”。
  • 另外,在另一个线程上运行“无更改”(即读取 UI 元素)的代码是不安全的。为了确保 UI 代码正确运行,它必须在 UI 线程上运行 - 用于所有读取和写入操作。
  • 很抱歉让您感到痛苦,但即使是“获得部分结果”也可能是错误的。无法保证看似只读的操作可能会在内部更新某些内容。编写这样的代码很容易。我们不知道框架代码在做什么。此外,可能存在竞争条件,其中纯只读操作将返回不是“部分”结果,而是完全不正确的结果。底线是您不能安全地在非 UI 线程上执行任何操作。
  • @Enigmativity 不,只有一个 UI 线程,它处理所有表单和控件。
  • @Andy - 是的,我知道。我只是评论说这个答案中的措辞可能会误导其他人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 2018-01-03
  • 2019-06-09
  • 1970-01-01
  • 2011-02-12
  • 2022-01-20
相关资源
最近更新 更多