0

シリアル通信を行うプログラムがあります。コマンドを送信した後、プログラムはデータを受信するまでしばらく待機する必要があります。データは ActiveX MsComm を使用して受信されます

http://msdn.microsoft.com/en-us/library/aa259393%28v=vs.60%29.aspx

疑似コードは次のようになります。

timer_tick

データを送信 (ノード 1)

sleep(500) 'その間、ノード 1 のデータを受信

データの送信 (ノード 2)

. . .

問題は、スリープが原因で GUI が遅れることです。いくつかの代替案を考えました

1) タイマーで人工カウンターを使用して、次のコマンドを送信する前に 500 ミリ秒を概算しますが、私にはあまり良い考えではないようです 2) タイマーの代わりにスレッドを使用しますか? バックグラウンドスレッドとして設定する

http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.71).aspx

3) application.doevents を利用していますか?

私はオプション 2 または 3 にあまり慣れていないため、コードに複雑な要素を導入することをためらっています。この問題により適した、またはオプション 2 または 3 に向けて作業を開始するための代替案を誰かアドバイスできますか?

4

2 に答える 2

2

この問題は、UI スレッドをスリープ状態にしているために発生します。.NET 4.5 では、Task.Delayスレッドをブロックすることなく、特定の間隔の後にのみコードを実行するために使用できます。

Dim port As New SerialPort
...
Public Async Sub SomeButton_Click()
    port.WriteLine("First")
    Await Task.Delay(500)
    port.WriteLine("Second")
    Await Task.Delay(300)
    port.WriteLine("Third")
End Sub

この場合、最初のWriteLine実行は UI スレッドで実行され、バックグラウンドで 500 ミリ秒 (実際にはタイマーを使用して) 待機が発生し、その後、元のスレッド (UI スレッド) で実行が再開され、2 番目の実行もWriteLineUI スレッドで発生します。さらに 300 ミリ秒待機すると、UI スレッドでも 3 番目の WriteLine が発生します。

このAsync\Await組み合わせにより、BackgroundWorker などの他のコンポーネントを使用せずに、このようなコードを非常にクリーンな方法で記述できます。また、複数の非同期呼び出しを実行するなど、バックグラウンド ワーカーではできないことも実行できます。そのような場合、複数のワーカーを使用する必要があります。ここで、もう 1 つのステートメントを記述するだけです。

このAsync Sub構文は、イベント ハンドラーに対してのみ使用されることに注意してください。それ以外の場合はすべて、 を使用する必要がありますAsync Function SomeFunction() As Task

シーケンス全体をバックグラウンド スレッドで実行する場合は、Task.Run.

Public Async Sub SomeButton_Click()
    Task.Run(Async Function () 
            Await SendAndWait
        End Function)
End Sub

public Async Function SendAndWait As Task
    _port.WriteLine("First")
    Await Task.Delay(500)
    _port.WriteLine("Second")
    Await Task.Delay(300)
    _port.WriteLine("Third")
End Function

タスクを使用する真の利点は、複数の非同期操作を組み合わせることができることです。これは、BackgroundWorker ではほぼ不可能です。この場合、非常に単純なコードを使用して、ファイルまたはデータベースからデータを非同期的に読み取り、シリアル ポートに非同期的に送信できます。

public Async Function SendAndWait(filePath As String) As Task
    Dim line As String
      Using reader As New StreamReader(filePath)            
        For i=0 To 3 
            line=Await reader.ReadLineAsync() 
            _port.WriteLine(line)
            Await Task.Delay(500)                
        Next 
    End Using 
End Function

プロジェクトにMicrosoft.Bcl.Asyncパッケージをasync/await追加することで、.NET 4.0 コードでもキーワードを使用できます。

于 2014-11-26T09:57:21.770 に答える