2017-01-23 21 views
0

バックグラウンドで実行されている非同期機能があります。この関数は、TCPを介してデータをポーリングします。私は現在の値を取得し、json形式で戻る別の関数GetClientNameByIdを持っています。しかし、すべての値に対してNULLを取得しています。途中で中断し、値を取得し、ポーリングを再開するにはどうすればよいですか?以下は私のコードです。割り込みと非同期

class Poll 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
    public string C { get; set; } 
    public string D { get; set; } 
    public string E { get; set; } 
} 

public async void Polling(CancellationToken token) 
{ 
    await Task.Run(() => 
    { 
     if (token.IsCancellationRequested) 
     { 
      return; 
     } 

     while (true) 
     { 
      if (token.IsCancellationRequested) 
      { 
       return; 
      } 

      //TODO 

      poll.A = reply1; 
      poll.B = reply2; 
      poll.C = reply3; 
      poll.D = reply4; 
      poll.E = DateTime.Now.ToString("HH:mm:ss.fff"); 
     }  
    }); 
} 

Poll poll = new Poll(); 
public string GetClientNameById(string Id) 
{ 
    string json = ""; 
    if (Id == "Poll") 
    { 
     Console.WriteLine("Reply: " + poll.A + " " + poll.B + " " + poll.C + " " + poll.D + " " + poll.E); 

     json = JsonConvert.SerializeObject(poll, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented }); 
    }  
    return json; 
} 
+0

'poll'変数はどこで宣言されインスタンス化されていますか? –

+0

そして、同じインスタンスが 'Polling'関数と' GetClientNameById'の間で共有されていることを確認しましたか?また、デバッグ中にコードが4つのプロパティを設定している 'Polling'の場所に到達したことを確認しましたか?そして、このコードに達して実行されると、 'GetClientNameById'の中でそれらの4つのプロパティがnullであることを確認しましたか? –

+0

@DarinDimitrov sry。私の悪い。私はあなたの質問を誤解しました。 'poll'は' GetClientNameById'の上に宣言されます – active92

答えて

0

あなたが含むクラスの異なるインスタンスにPollingGetClientNameById関数を呼び出しているように見えます。あなたのpoll変数はこのクラスを含むフィールドとして宣言されているので、その新しいインスタンスが毎回作成されます。

すると、同じインスタンス上でこれらの関数を呼び出していることを確認してください:

var myContainingClass = new MyContainingClass(); 
// Start polling 
await myContainingClass.Polling(someCancellationToken); 

// Call the GetClientNameById function on the same instance 
// on which you called the Polling function 
myContainingClass.GetClientNameById("Poll"); 
myContainingClass.GetClientNameById("Poll"); 
myContainingClass.GetClientNameById("Poll"); 
... 

はまた、あなたのコード内のレースの条件があります。ポーリング機能の中に4つのフィールドが割り当てられているので、GetClientNameById関数を同時に呼び出した場合、を参照してください。これらのフィールドは、TCP呼び出しのさまざまな呼び出しから割り当てられます。あなたは、ゲートウェイを使用して、この投票の変数へのアクセスを同期化することを考慮可能性がありますフィールドを書くときに

private readonly ReaderWriterLockSlim gateway = new ReaderWriterLockSlim(); 

と書き込みロックを取得:

gateway.EnterWriteLock(); 
try 
{ 
    poll.A = reply1; 
    poll.B = reply2; 
    poll.C = reply3; 
    poll.D = reply4; 
    poll.E = DateTime.Now.ToString("HH:mm:ss.fff"); 
} 
finally 
{ 
    gateway.ExitWriteLock(); 
} 

と読み:

if (Id == "Poll") 
{ 
    gateway.EnterReadLock(); 
    try 
    { 
     Console.WriteLine("Reply: " + poll.A + " " + poll.B + " " + poll.C + " " + poll.D + " " + poll.E); 

     json = JsonConvert.SerializeObject(poll, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented }); 
    } 
    finally 
    { 
     gateway.ExitReadLock(); 
    } 
} 

両方の関数呼び出しで同じインスタンスを使用したくない場合は、pollフィールドを静的にして、すべてのインスタンス間で共有することを検討することもできます。レースの状態に関する発言はまだ適用され、このフィールドへのアクセスを適切に同期させる必要があります。

+0

お世話になりました。私はいくつかの調査を行い、 'ReaderWriterLockSlim'は' async-await'にはお勧めできません。したがって、代わりに 'SemaphoreSlim'を使用しました。 – active92

関連する問題