2016-11-30 12 views
2

アプリケーションでスレッドを使用しようとしたのは初めてです。 私はこの質問が以前に尋ねられたことを知っていますが、私が見た解決策は私の状況でそれらを適用する方法を見ることができません。c#別のスレッドを開始する前にスレッドをチェックする方法は完了しました

データグリービューが60秒ごとにタイマーでリフレッシュされるプログラムがあります。データはSQLデータベースから得られます。このタイマーはワーカースレッドを開始して、特定のBluetoothデバイスを検索し、バックグラウンドでの検出結果に基づいてデータベースを更新します。ブルートゥースのルックアップは特に遅いので、私はそれをワーカースレッドに入れています。

私の問題は、新しいワーカースレッドが前のスレッドが終了する前に開始されることがあります。少なくとも、それは私が得ているエラーの唯一の論理的な説明です。大きな問題は、ファイルをロックできる唯一のことが同じアプリケーションの別のワーカースレッドである場合、ファイルロックエラーです。

私はバックグラウンドスレッドを開始するために使用しているコードです。

private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

    // If the user is not on a Remote desktop connection 
    if (!remoteDesktopUser) 
    { 

     // Run the Bluetooth Search in a worker thread 
     Thread thread = new Thread(new ThreadStart(this.checkProximity)); 
     thread.IsBackground = true; 
     thread.Start(); 
    } 

    // Load User Data from the DB and display on the screen 
    loadUserData(); 
} 

解決策がthread.IsAlive()を使用することですが、私は良い例を見つけることができていないように見えるだろう。 "Thread thread = new Thread()"を使って新しいスレッドを作成したばかりのスレッドの存在を確認しようとするのは、奇妙に思えます。

明らかに私は何かが不足しています。 I私は変更...私はこれを試してみました下のkrw12572によって提案された解決策に基づいてUPDATE

をデビッド

のVisual Studioに

を任意のアイデアを2008年 感謝を使用しています!=に==私はまだ毎回、プライマリスレッドでloadUserData()メソッドを実行したいからです。

エディタでフィールドが割り当てられていないことを示す「_bluetoothSearchThread」の緑色の下線が表示され、常に値がNULLになります。

実行時に、この行に「オブジェクト参照がオブジェクトのインスタンスに設定されていません」というエラーが表示されます。

if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive) 

この値はどのように割り当てられますか?

private Thread _bluetoothSearchThread; 
    private void timerScreenRefresh_Tick(object sender, EventArgs e) 
    { 
     if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

     // Check if Worker Thread is already running. 
     if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive) 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running"); 

      // If the user is not on a Remote desktop connection 
      if (!remoteDesktopUser) 
      { 
       // Check if the users mobile phone is within range 
       // Run the Bluetooth Search in a worker thread 

       Thread thread = new Thread(new ThreadStart(this.checkProximity)); 
       thread.IsBackground = true; 
       thread.Start(); 
      } 
     } 
     else 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Worker Thread still running don't start another one"); 
     } 

     // Load User Data from the DB and display on the screen 
     loadUserData(); 
    } 

アップデート2

OK私は、私はそれを考え出したと思います。 != Nullを元の状態に戻して、IFとそれ以外の方法を逆にしました。

は、その後、私は私の脳ビットを使用していたと「_bluetoothSearchThread」

今のコードはコンパイルして実行するには、「スレッド」に変更しました。今では、ファイルロックエラーの原因となっている条件をトリガーして、実際に元の問題を修正したかどうかを確認するだけです。それがうまくいけば、私はkrw12572の答えを正しいとマークします。

更新2。5 は、私もそれがあまりにも早く

_bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 

新しいインスタンスを作成しませんので、これは実用的なソリューションがあるので、この線を移動しなければなりませんでした。

private Thread _bluetoothSearchThread; 
    private void timerScreenRefresh_Tick(object sender, EventArgs e) 
    { 
     if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 


     // Check if Worker Thread is already running. 
     if (_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive) 
     { 
      // Thread is still running. Just log it and move on. 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "******** Worker Thread still running don't start another one *********"); 
     } 
     else 
     { 
      if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running"); 

      // If the user is not on a Remote desktop connection 
      if (!remoteDesktopUser) 
      { 
       // Check if the users mobile phone is within range 
       // Run the Bluetooth Search in a worker thread 
       _bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 
       _bluetoothSearchThread.IsBackground = true; 
       _bluetoothSearchThread.Start(); 
      } 
     } 

     // Load User Data from the DB and display on the screen 
     loadUserData(); 
    } 
+0

ここにあなたの結果:http://stackoverflow.com/questions/12949024/detecting-a-thread-is-already-running-in-c-sharp-net –

+0

@BALA私はその解決策を以前に見ました。それは過度に複雑に思え、私はそれを本当に理解していませんでした。私は明日それを盲目的に追いかけ、実行可能なものが出てくるかどうかを見てみましょう。 –

+0

[スレッドが実行を終了したかどうかをチェックする方法]の複製があります(http://stackoverflow.com/questions/2773479/how-to-check-if-thread-finished-execution) –

答えて

4

一度に実行しているスレッドを1つだけしたい場合は、インスタンスをスレッド格納するフィールドを作成することができます。そのスレッドインスタンスを使用して、すでに実行中かどうかを_threadInstance.IsAliveで確認できます。

private Thread _bluetoothSearchThread; 
private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    if(_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive) 
     return;  //It means one thread is already performing the search operation. 

    if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", ""); 

    // If the user is not on a Remote desktop connection 
    if (!remoteDesktopUser) 
    { 

     // Run the Bluetooth Search in a worker thread 
     _bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 
     _bluetoothSearchThread.IsBackground = true; 
     _bluetoothSearchThread.Start(); 
    } 

    // Load User Data from the DB and display on the screen 
    loadUserData(); 
} 
+0

私はそれを試みました。それにはいくつかの問題がありました。提案されたソリューションとエラーメッセージを含めるように質問を更新しました。ありがとうDavid –

+0

私は私の答えを更新しました。 Thread thread = new Thread(..)を作成する代わりに、新たに作成されたフィールドをスレッドインスタンスに使用します。 _bluetoothSearchThread =新しいスレッド(...) –

4

EDIT:

あなたsitutationでThread.IsAliveを使用して、研究した後、それを行うための安全な方法ではありません。

あなたは使うべきThrea.Join()

ドキュメント:

ブロック呼び出し元のスレッド に継続する標準COMとのSendMessageを実行しながら、この インスタンスによって表されるスレッドは、指定した時間が経過終了するまで、またはポンピング。

例:

while(!currentThread.Join(0)) //should specify the time if you dont want it to be blocking. 
{ 
    ///thread is ongoing 
} 
Console.WriteLine("while loop has breaked! so the thread is finished!"); 
+0

サンプルコードでThread.IsAliveをどのように使用しますか?私にいくつかのアイデアをお願いしますか? –

+0

@DavidPollard 'if(thread.isAlive)//次に何でもします。 ' –

+0

@DavidPollardこんにちは、私はaswerを編集しました –

0

あなたはTaskの代わりThreadを使用する場合があります。

// Create dummy task 
Task task = Task.Run(() => { }); 

private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    ... 
    // add continuation to current task 
    task.ContinueWith(t => checkProximity); 
    ... 
} 

新しいタスクは、前のタスクの後にのみ実行されます。

ただし、Tickの間にタスクを実行する時間がない場合は、キューに蓄積されます。

+0

こんにちはアレクサンダー、私はサブタスクを待ち行列に入れているわけではありませんが、代わりにタスクを考えていました。私は今、krw12572が示唆していることを理解しています。テストするために、私は10秒に私のタイマーの目盛りを設定し、私はそれが開け閉めのスレッドであった私のログから見ることができた。上記のコードを使用すると、素敵で整然としたものになります。スレッド11が開始され、スレッド11が終了するまで何も開始されません。だから私が今取得する他のエラーは、スレッドの重複には関係しません。あなたのアイデアをありがとう。デビッド –

関連する問題