2016-06-27 21 views
1

コールバック関数を持つタイマーを起動します。しかし、このコールバック関数では、タイマーの起動後に使用される静的オブジェクトを変更/初期化します。Threading.Timerコールバック関数が終了するのを待つ

public class TimerExecute 
{ 
    // Assume that the "Dog" class exist with attribute Name initialized in the constructor 
    public static List<Dog> listDog = new List<Dog>(); 

    public void callbackFunct(String param) { 

     // code... 

     listDog.Add(new Dog("Bob")); 

     // code... 
    } 

    public void Main() { 
     // add dogs Bob each 10sec 
     Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000); 

     // return argumentoutofrange exception 
     Console.WriteLine(listDog[0].name); 
    } 
} 

static varを使用すると、例外「out of range exception」が発生します。私は問題は、コールバック関数が彼女の実行を完了せず、オブジェクトがまだ初期化されていないことだと思います。

私は、このソリューションを試してみましたが、これは動作しません:

// add dogs Bob each 10sec 
Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000); 
WaitHandle h = new AutoResetEvent(false); 
addbobs.Dispose(h); 
Console.WriteLine(listDog[0].name); 

しかし、これで、それが動作します:

Timer addbobs = new Timer((e) => callbackFunct("arg"), null, 0, 10000); 
Thread.Sleep(2000); 
Console.WriteLine(listDog[0].name); 

私は私のコールバック関数は、次のステートメントの前に彼女の実行を終了することを望みます。 あなたは私の問題の解決策をお持ちですか?

最終編集:はい、私はあなたがnew TimerCallback(callbackFunct)の代わりに、関数の名前だけであなたのTimerCallbackを初期化する必要がありますかなり確信しているcallbackFunct

+1

null参照例外が発生することはありません。範囲外のインデックス例外が発生する可能性があります。例外の正確な表現を教えていただけますか? –

+0

ありがとうございます。「範囲外の例外」 – Neyoh

+0

'new Timer(callbackFunct、null、0、10000);'はコンパイルされません。実際に使用しているコードを投稿したり、サンプルコードを修正してコンパイルできますか? – Quantic

答えて

1

私が思いついたのはここです。そのトリックはAutoResetEventを渡すことです。このイベントでは、メソッドが完了したかどうかを示す信号であるSet()を呼び出す必要があります。 WaitHandleに加えて、コールバックに送られた他のパラメータが必要なので、私は両方をカプセル化するためのクラスを作成しました。

 public void callbackFunct(object state) 
     { 
      var myParams = (CustomParametersWithWaitHandle)state; 
      string name = myParams.Parameter1; 
      AutoResetEvent wh = myParams.WaitHandle; 
      // code... 

      listDog.Add(new Dog(name)); 

      // code... 

      wh.Set(); // signal that this callback is done 
     } 

     public void Main() 
     { 
      // add dogs Bob each 10sec 
      AutoResetEvent wh = new AutoResetEvent(false); 
      var myCustomParams = new CustomParametersWithWaitHandle(wh, "bob", 314); 
      Timer addbobs = new Timer(new TimerCallback(callbackFunct), myCustomParams, 0, 10000); 
      wh.WaitOne(); // blocks here until `Set()` is called on the AutoResetEvent 

      Console.WriteLine(listDog[0].name); 
     } 
    } 

    public class CustomParametersWithWaitHandle 
    { 
     public AutoResetEvent WaitHandle { get; set; } 
     public string Parameter1 { get; set; } 
     public int Parameter2 { get; set; } 

     public CustomParametersWithWaitHandle(AutoResetEvent h, string parameter1, int parameter2) 
     { 
      WaitHandle = h; 
      Parameter1 = parameter1; 
      Parameter2 = parameter2; 
     } 
+0

ああ素敵なトリック、私はパスを優先します私のようなコールバック関数で直接私のパラメータ。しかし、私はこれを試してみます、私はあなたをループに入れておきます – Neyoh

+0

これは間違っているかもしれないので、私はこのことについて学びました。しかし、私が理解していることから、あなたが従っている例は、 'AutoResetEvent'に対してコールバック関数を使用する必要があることを意味し、コールバックのパラメータは、' event.Set() 'をonそのため、コールバック関数のパラメータとして 'string'を渡すことはできません。なぜなら、' object'のイベントシグネチャを取り込まなければならず、そのオブジェクトに 'AutoResetEvent'があるからです。だから私のカスタムクラスでは、今も独自のパラメータがあります。 – Quantic

+0

それは働く、ありがとう – Neyoh

0

にパラメータを渡すことができるようにしたいです。それはあなたのリストがボブで満たされていない理由です(私はそれがどのようにコンパイルされるのか分かりませんが...)。同様に:

Timer addbobs = new Timer(new TimerCallback(callbackFunct), null, 0, 10000); 

あなたの関数は次のようになりなければならない。

public void callbackFunct(object state){ 
     //... 
     listDog.Add(new Dog("Bob")); 
     //... 
} 

... PS新しいインスタンスなしでそれを初期化することは可能かもしれないが、私はかなりよく分からない:Iそれはコンパイルされていないので、あなたが使用しているコードではないと思われます。それを更新するために気をつけてください...

+0

"あなたのリストがBobsで満たされていない理由であるはずです。彼のコードはコンパイルされていないので、あなたがコンパイルしたコードと異なるコードを実行しなければならないので、あなたのコンパイルの修正が実際に彼の問題を修正するかどうかは言い難いです。 – Quantic

+0

私はそう思っていますが、彼の編集を見ると、遅れてボブを埋めるので、彼の機能は大丈夫だと思っています。 –

関連する問題