【问题标题】:C# Thread issuesC# 线程问题
【发布时间】:2010-04-05 17:29:02
【问题描述】:

我正在做的是从上一个按钮单击动态创建的列表视图。然后 ti 启动一个后台工作程序,其中应清除列表视图并每 30 秒用新信息填充 iistview。
我不断得到:跨线程操作无效:控件'listView2'从创建它的线程以外的线程访问。

  private void watcherprocess1Updatelist()
    {
        listView2.Items.Clear();
        string betaFilePath1 = @"C:\Alpha\watch1\watch1config.txt";
        using (FileStream fs = new FileStream(betaFilePath1, FileMode.Open))
        using (StreamReader rdr = new StreamReader((fs)))
        {
            while (!rdr.EndOfStream)
            {
                string[] betaFileLine = rdr.ReadLine().Split(',');
                using (WebClient webClient = new WebClient())
                {
                    string urlstatelevel = betaFileLine[0];
                    string html = webClient.DownloadString(urlstatelevel);
                    File.AppendAllText(@"C:\Alpha\watch1\specificconfig.txt", html);
                }
            }
        }

【问题讨论】:

    标签: c#


    【解决方案1】:

    您无法从后台线程访问您的 ListView。您需要在 UI 线程上执行此操作。

    有两个选项 - 首先,您可以切换它以使用 Windows.Forms.Timer 每 30 秒触发一次。这将发生在 UI 线程上,这将完全避免此问题,但将处理移至 UI 线程。如果您的处理速度很慢,这可能会导致“挂起”。

    或者,使用 Control.Invoke 将对 ListView 的调用编组回 UI 线程:

     listView2.Invoke(new Action( () => listView2.Items.Clear() ) );
    

    无论如何,我都会重新考虑使用 BackgroundWorker。它不适用于定期发生的“定时事件”。如果没有长时间的处理,您应该考虑更改为 Windows.Forms.Timer(UI 线程),如果处理需要一段时间,则应考虑更改为 System.Timers.Timer(在后台线程上运行)。这是一个比永不终止的 BackgroundWorker 更好的设计选项。

    【讨论】:

    【解决方案2】:

    你需要使用Control.Invoke调用UI线程上的代码来更新listView。

    【讨论】:

      【解决方案3】:

      这是我用于会与 UI 控件混淆的方法的模式

      public void DoSomethingToUI(string someParams)
      {
          if(UIControl.InvokeRequired)
          {
              UIControl.BeginInvoke(()=>DoSomethingToUI(someParams));
              return;
          }
          //Do something to the UI Control
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-08
        • 2011-09-30
        • 2011-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多