2016-08-03 3 views
4

저는 방금 비동기를 사용하기 시작했기 때문에이 작업을 시작하려고합니다. 그래서 나는 현재 내가하고있는 일에 대해 매우 제한된 이해를하고 있습니다.직렬 포트에서 계속 비동기 적으로 계속 읽음

이전에 직렬 포트에서 데이터를 읽는 쓰레드를 사용하여 데이터를 처리하여 데이터를 쓰고 쓰는 중이었습니다. 나는 1 개의 쓰레드가 데이터를 읽고 그것을 버퍼에 놓고, 다른 쓰레드가 버퍼에서 데이터를 처리하고, 마지막 쓰레드가 그것을 쓰도록했다. 이렇게하면 버튼을 클릭하면 추가 데이터를 보낼 수 있습니다.

이제 모든 것을 제대로하고 있는지 확인하기 위해 직렬 포트에서 데이터를 읽고 다중 텍스트 상자에 데이터를 추가하려고합니다. 여기에 코드입니다 :

연결 직렬 포트가 성공하면,이다 UpdateMessageBox를 호출 비동기 :

public async Task UpdateMessageBox() 
{ 
    messageTextBox.Text += "Reading data from serial."; 
    while (_serialConnected) 
    { 
     string message = await SerialReadLineAsync(serial); 
     messageTextBox.Text += message; 
    } 
} 

그리고 이것은이 지속적으로 ReadLineAsync를 호출하고 텍스트 상자에 결과를 추가

private void serialConnectClick(object sender, EventArgs e) 
{ 
    if (!_serialConnected) 
    { 
     _serialConnected = SerialConnect(portCombo.Text, int.Parse(baudCombo.Text)); 
     if (!_serialConnected) 
     { 
      portCombo.SelectedIndex = 0; 
      messageTextBox.Text += "Failed to connect.\r\n"; 
      return; 
     } 

     serialConnectBtn.Text = "Disconnect"; 
     serialStatusLabel.Text = "Serial: Connected"; 
     serialStatusLabel.ForeColor = Color.Blue; 
     messageTextBox.Text += "Connected\r\n"; 
     VDIportCombo.Enabled = false; 
     soundSuccess.Play(); 
     UpdateMessageBox(); // this is an async function 
    } 
} 

SerialPort.BaseStreamReadAsync을 입력하고 전체 줄 (줄 바꿈 문자로 표시)을 얻을 때만 데이터를 반환합니다.

async Task<string> SerialReadLineAsync(SerialPort serialPort) 
{ 
    byte[] buffer = new byte[1]; 
    string result = string.Empty; 
    Debug.WriteLine("Let's start reading."); 

    while (true) 
    { 
     await serialPort.BaseStream.ReadAsync(buffer, 0, 1); 
     result += serialPort.Encoding.GetString(buffer); 

     if (result.EndsWith(serialPort.NewLine)) 
     { 
      result = result.Substring(0, result.Length - serialPort.NewLine.Length); 
      result.TrimEnd('\r','\n'); 
      Debug.Write(string.Format("Data: {0}", result)); 
      result += "\r\n"; 
      return result; 
     } 
    } 
} 

나는 모든 것을 올바르게하고 있습니까? UI 스레드에서 비동기 메서드를 호출 할 수 있습니까? 비주얼 스튜디오에서 나는 사용해야한다고 말하고 있지만, 그저 제안하는 것일뿐입니다.

지속적으로 읽는 동안 다른 코드가 UI 스레드에서 실행되기를 원하므로 awaitUpdateMessageBox 기능을 사용하고 싶지 않습니다. 이 스레드 경우, 난 그냥 백그라운드에서 작동하는 읽기 스레드를 원할 것입니다, 그리고 난 그냥 할 것이라고 myReadThread.Start(), 거기에 비동기 뭔가 비슷한가?

편집 :이 코드는 작동하지만, 내가하고있는 일을하는 "적절한"방법인지 알고 싶습니다.

await UpdateMessageBox().ConfigureAwait(true); 

UpdateMessageBox 포착하기 위해 ConfigureAwait(true)를 사용해야합니다

private void serialConnectClick(object sender, EventArgs e) 

private async void serialConnectClick(object sender, EventArgs e) 

에 ... 그리고에 UpdateMessageBox();에 전화를 변경합니다

답변

6

당신은 변경해야 현재 컨텍스트 (UI)이면(10) 다른 스레드에서 실행됩니다 : SerialReadLineAsync에서

public async Task UpdateMessageBox() 
{ 
    messageTextBox.Text += "Reading data from serial."; 
    while (_serialConnected) 
    { 
     string message = await SerialReadLineAsync(serial).ConfigureAwait(true); 
     messageTextBox.Text += message; 
    } 
} 

, 당신은 변경할 수 있습니다

await serialPort.BaseStream.ReadAsync(buffer, 0, 1); 

...에 :

await serialPort.BaseStream.ReadAsync(buffer, 0, 1).ConfigureAwait(false); 

을 ... SerialReadLineAsync 문이 관련되지 않기 때문에 UI에.

일반적인 팁은 await이 방법은 또한 asyncasync 차례로 await ED하여 이루어질 필요 s의 임의의 방법을 의미 "줄곧 비동기". call-stack을 반복합니다.

+0

아, 그 기능을 비동기로 만들 수 있다는 것을 몰랐습니다! 'UpdateMessageBox'를 '기다릴 필요가없는 방법이 있습니까? 'await' 키워드를 포함 시키면 두 번째 버튼 (현재 직렬 포트를 닫도록 프로그래밍되어 있음)을 누르면 IOException이 발생합니다. –

+0

앞으로 누구에게나! '.ConfigureAwait (false);를 추가하면됩니다.'UpdateMessageBox(). ConfigureAwait (false);' –

+1

수 있습니다. UI 메소드에서'ConfigureAwait (false)'를 사용하는 것에주의하십시오. 그렇지 않으면 바로 뒤의 명령문이 다른 스레드에서 잠재적으로 실행될 수 있습니다. 그렇지 않으면, 당신이 쓰레드에 대해 신경 쓰지 않는다면'ConfigureAwait (false)'를 사용하십시오. [추가 정보] (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx) – MickyD

관련 문제