0
class ...
{
   onClick()
   {
      while(true)
      {
        //call the thread from here
        threadpool(request)//send request to thread using thread pool
      }
   }

   //the function for thread
   threadfunction()//function that thread calls
   {

   // I am not able to change the textbox/datagridview in windowsform from here the main ui gets stuck // 

   }
}

我不想更改上述逻辑是否可以从线程函数同时更新数据网格,因为我的程序卡住了。

4

6 回答 6

3

while (true)应该在线程函数中,而不是在 onClick 中。否则 GUI 会卡住,因为它无休止地执行while(true).

于 2011-09-21T12:27:21.543 回答
2

根据给定的代码while(true)永远运行。如果你有一个耗时的过程,你将不得不使用一个单独的线程来处理它。如果您在主线程(UI 线程)中执行该耗时的过程,它将很忙,并且在完成该任务之前不会考虑您的 UI 更改请求。这就是您体验 UI 冻结的原因。

如果您将 backgroundWorker 用于耗时的任务,您将能够实现您想要的。您必须在BackgroundWorkder.DoWork方法的while(true)子句中实现逻辑。

关于BackgroundWorker的几点...

在不同的线程中DoWork,向主线程报告进度并取消异步进程是BackgroundWorker中最重要的功能。下面的示例非常清楚地展示了这三个功能。网络上有大量示例可用。

using System;
using System.Threading;
using System.ComponentModel;

class Program
{
  static BackgroundWorker _bw;

  static void Main()
  {
    _bw = new BackgroundWorker
    {
      WorkerReportsProgress = true,
      WorkerSupportsCancellation = true
    };
    _bw.DoWork += bw_DoWork;
    _bw.ProgressChanged += bw_ProgressChanged;
    _bw.RunWorkerCompleted += bw_RunWorkerCompleted;

    _bw.RunWorkerAsync ("Hello to worker");

    Console.WriteLine ("Press Enter in the next 5 seconds to cancel");
    Console.ReadLine();
    if (_bw.IsBusy) _bw.CancelAsync();
    Console.ReadLine();
  }

  static void bw_DoWork (object sender, DoWorkEventArgs e)
  {
    for (int i = 0; i <= 100; i += 20)
    {
      if (_bw.CancellationPending) { e.Cancel = true; return; }
      _bw.ReportProgress (i);
      Thread.Sleep (1000);      // Just for the demo... don't go sleeping
    }                           // for real in pooled threads!

    e.Result = 123;    // This gets passed to RunWorkerCompleted
  }

  static void bw_RunWorkerCompleted (object sender,
                                     RunWorkerCompletedEventArgs e)
  {
    if (e.Cancelled)
      Console.WriteLine ("You canceled!");
    else if (e.Error != null)
      Console.WriteLine ("Worker exception: " + e.Error.ToString());
    else
      Console.WriteLine ("Complete: " + e.Result);      // from DoWork
  }

  static void bw_ProgressChanged (object sender,
                                  ProgressChangedEventArgs e)
  {
    Console.WriteLine ("Reached " + e.ProgressPercentage + "%");
  }
}

这里查看更多详细信息。

于 2011-09-21T12:30:38.000 回答
2

首先,不要在回调中创建无限循环,因为 UI 线程将永远运行该循环。然后,如果threadfunction()需要 UI 更新,您必须将代码重新同步到 UI 线程:

threadfunction()
{
 myControl.Update(result);
}

class TheControl
{
 public void Update(object result)
 {
  if (this.InvokeRequired)
   this.Invoke(new Action<object>(Update), result);
  else
  {
   // actual implementation
  }
 }
}
于 2011-09-21T12:33:46.547 回答
0

我会假设主(gui)线程因为循环而冻结(不清楚你是否在那里以某种方式处理事件)。此外,要从另一个线程内部更改 gui,您必须调用 Invoke 并让委托更改所需的值。

于 2011-09-21T12:30:51.477 回答
0

不能从单独的线程直接访问 Windows 窗体控件。您可能想使用Control.Invoke更改 textbox/datagridview 属性
查看MSDN 文章。关于从单独的线程访问控件。

于 2011-09-21T12:31:19.433 回答
0

考虑在 UI 线程执行其他操作时使用 async-await 处理输入并更新结果。

事件处理程序:

private async void OnButton1_clicked(object sender, ...)
{
    var result = await ProcessInputAsync(...)
    displayResult(result);
}

假设 ProcessInputAsync 是耗时的函数。DisplayResult由UI线程调用,可以正常处理。

注意:所有异步函数都应该返回 Task 而不是 void 或 Task <Tresult> 而不是 TResult。有一个例外:异步事件处理程序应该返回 void 而不是 Task。

private async Task<TResult> ProcessInputAsync(...)
{
    return await Task.Run( () => LengthyProcess(...)
}

private TResult LengthyProcess(...)
{
    // this is the time consuming process.
    // it is called by a non-ui thread
    // the ui keeps responsive
    TResult x = ...
    return x;
 }

如果您真的不想等待冗长的过程完成,但您希望另一个线程更新 UI,您会收到一个运行时错误,即未创建 UI 元素的线程尝试更新它。为此,我们有调用模式:

private void UpdateMyTextBox(string myTxt)
{
    if (this.InvokeRequired)
    {   // any other thread than the UI thread calls this function
        // invoke the UI thread to update my text box
        this.Invoke(new MethodInvoker(() => this.UpdateMyTextBox(myTxt));
    }
    else
    {
        // if here: this is the UI thread, we can access the my text box
        this.TextBox1.Text = myTxt;
    }
}
于 2015-08-10T14:52:11.720 回答