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 変更要求が考慮されません。そのため、UI がフリーズします。

時間のかかるタスクに backgroundWorker を使用すると、目的を達成できます。BackgroundWorkder.DoWorkメソッドのwhile(true)句にロジックを実装する必要があります。

BackgroundWorker に関するいくつかのポイント...

別のスレッドで作業を行い、メイン スレッドに進行状況を報告し、非同期プロセスをキャンセルすることは、BackgroundWorker で最も重要な機能です。以下の例は、これら 3 つの機能を非常に明確に示しています。ウェブ上で利用可能な例が山ほどあります。

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.Invoketextbox/datagridview のプロパティを変更するために使用したい場合があります。MSDN の記事
を 確認してください。別のスレッドからのコントロールへのアクセスについて。

于 2011-09-21T12:31:19.433 に答える