데이터를 USB HID 클래스 장치로 전송하는 WinForms 응용 프로그램을 작성 중입니다. 내 응용 프로그램을 찾을 수있는 우수한 일반 HID 라이브러리 6.0 사용 여기를 . 간단히 말해서, 장치에 데이터를 써야 할 때 이것이 호출되는 코드입니다.
private async void RequestToSendOutputReport(List<byte[]> byteArrays)
{
foreach (byte[] b in byteArrays)
{
while (condition)
{
// we'll typically execute this code many times until the condition is no longer met
Task t = SendOutputReportViaInterruptTransfer();
await t;
}
// read some data from device; we need to wait for this to return
RequestToGetInputReport();
}
}
코드가 while 루프에서 빠지면 장치에서 일부 데이터를 읽어야합니다. 그러나 장치가 바로 응답 할 수 없으므로 계속 진행하기 전에이 통화가 돌아올 때까지 기다려야합니다. 현재 존재하므로 RequestToGetInputReport ()는 다음과 같이 선언됩니다.
private async void RequestToGetInputReport()
{
// lots of code prior to this
int bytesRead = await GetInputReportViaInterruptTransfer();
}
가치가있는 것에 대한 GetInputReportViaInterruptTransfer () 선언은 다음과 같습니다.
internal async Task<int> GetInputReportViaInterruptTransfer()
불행히도, 나는 .NET 4.5의 새로운 비동기 / 대기 기술의 작동에 익숙하지 않습니다. 나는 await 키워드에 대해 조금 읽었고 RequestToGetInputReport () 내부의 GetInputReportViaInterruptTransfer () 호출이 대기 할 것이라는 인상을 받았지만 RequestToGetInputReport () 호출과 같지 않습니다. while 루프를 거의 즉시 다시 입력하기 때문에 자체적으로 기다리고 있습니까?
아무도 내가보고있는 행동을 분명히 할 수 있습니까?
답변
피하십시오 async void
. Task
대신 메소드를 반환하십시오 void
. 그럼 당신은 할 수 await
있습니다.
이처럼 :
private async Task RequestToSendOutputReport(List<byte[]> byteArrays)
{
foreach (byte[] b in byteArrays)
{
while (condition)
{
// we'll typically execute this code many times until the condition is no longer met
Task t = SendOutputReportViaInterruptTransfer();
await t;
}
// read some data from device; we need to wait for this to return
await RequestToGetInputReport();
}
}
private async Task RequestToGetInputReport()
{
// lots of code prior to this
int bytesRead = await GetInputReportViaInterruptTransfer();
}
답변
가장 중요한 것은에 대해 알아야 할 사항 async
과 await
그가 await
되지 않습니다 완료 될 때까지 관련 전화 기다립니다. 어떤 await
일은 즉시 동 기적으로 작업의 결과를 반환하는 작업이 이미 완료 한 경우 나, 그렇지 않은 경우의 나머지 실행하기 위해 계속 예약 async
방법을 다음 호출자에게 컨트롤을 반환 할 수 있습니다. 비동기 작업이 완료되면 예약 완료가 실행됩니다.
질문 제목의 특정 질문에 대한 답변 은 적절한 메소드 를 호출하여 async
메소드의 반환 값 ( Task
또는 유형이어야 함 )을 차단하는 것입니다 .Task<T>
Wait
public static async Task<Foo> GetFooAsync()
{
// Start asynchronous operation(s) and return associated task.
...
}
public static Foo CallGetFooAsyncAndWaitOnResult()
{
var task = GetFooAsync();
task.Wait(); // Blocks current thread until GetFooAsync task completes
// For pedagogical use only: in general, don't do this!
var result = task.Result;
return result;
}
이 코드 스 니펫 CallGetFooAsyncAndWaitOnResult
은 비동기 메소드 주위 의 동기 랩퍼 GetFooAsync
입니다. 그러나이 패턴은 비동기 작업 중에 전체 스레드 풀 스레드를 차단하므로 대부분 피해야합니다. 이는 API에 노출 된 다양한 비동기 메커니즘을 비효율적으로 사용하여이를 제공하기 위해 많은 노력을 기울입니다.
“await” 의 답변 은 통화 가 완료 될 때까지 기다리지 않습니다 . 이러한 키워드에 대한 자세한 설명이 몇 가지 있습니다.
한편 @Stephen Cleary의 지침은 async void
보류입니다. 이유에 대한 다른 좋은 설명은 http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/ 및 https://jaylee.org/archive/ 에서 찾을 수 있습니다. 2012 / 07 / 08 / c-sharp-async-tips-and-tricks-part-2-async-void.html
답변
AsynMethod가 작업을 완료 할 때까지 기다리는 가장 좋은 방법은
var result = Task.Run(async() => await yourAsyncMethod()).Result;
답변
다음은 플래그를 사용하는 해결 방법입니다.
//outside your event or method, but inside your class
private bool IsExecuted = false;
private async Task MethodA()
{
//Do Stuff Here
IsExecuted = true;
}
.
.
.
//Inside your event or method
{
await MethodA();
while (!isExecuted) Thread.Sleep(200); // <-------
await MethodB();
}
답변
작업이 완료 될 때까지 대기하기 위해 Wait ()를 넣으십시오.
GetInputReportViaInterruptTransfer().Wait();
답변
다음 스 니펫은 호출자에게 리턴하기 전에 대기중인 메소드가 완료되도록하는 방법을 보여줍니다. 그러나 나는 그것이 좋은 습관이라고 말하지 않을 것입니다. 당신이 다르게 생각한다면 설명과 함께 내 대답을 편집하십시오.
public async Task AnAsyncMethodThatCompletes()
{
await SomeAsyncMethod();
DoSomeMoreStuff();
await Task.Factory.StartNew(() => { }); // <-- This line here, at the end
}
await AnAsyncMethodThatCompletes();
Console.WriteLine("AnAsyncMethodThatCompletes() completed.")
답변
실제로 이것은 IAsyncAction을 반환하는 함수에 더 유용하다는 것을 알았습니다.
var task = asyncFunction();
while (task.Status == AsyncStatus.Completed) ;
