"이전 내장 대리자"를 종료 실행 중단
나는 더 단순함을 바라면서 이전의 fire-and-forget 호출을 새로운 구문으로 바꾸려고 노력하고 있는데 그것은 나를 피하는 것입니다. 여기에 예가 있습니다.
class Program
{
static void DoIt(string entry)
{
Console.WriteLine("Message: " + entry);
}
static async void DoIt2(string entry)
{
await Task.Yield();
Console.WriteLine("Message2: " + entry);
}
static void Main(string[] args)
{
// old way
Action<string> async = DoIt;
async.BeginInvoke("Test", ar => { async.EndInvoke(ar); ar.AsyncWaitHandle.Close(); }, null);
Console.WriteLine("old-way main thread invoker finished");
// new way
DoIt2("Test2");
Console.WriteLine("new-way main thread invoker finished");
Console.ReadLine();
}
}
두 접근 방식 모두 동일한 작업을 수행하지만 내가 얻은 것 ( EndInvoke
핸들을 닫을 필요 가없고 아직 논란의 여지가 있음)을 기다려야하는 새로운 방식으로 잃고 있습니다. Task.Yield()
실제로 새로운 문제를 제기합니다. 한 줄을 추가하기 위해 기존의 모든 것이 F & F 메소드를 다시 작성해야합니다. 성능 / 정리에서 보이지 않는 이점이 있습니까?
백그라운드 방법을 사용할 수없는 경우 어떻게 적용 할 수 있습니까? 확고한 방법이없는 것입니다. Task.Run ()을 기다리고 래퍼를 사용하는 방법?
편집 : 이제 실제 질문이 누락되어 있습니다. 질문은 다음과 가변합니다. 동기 방식 A ()가 주어지면 "이전 방식"보다 더 복잡한 솔루션을 얻지 않고 화재 및 잊어 버리기 방식으로 async
/ await
를 사용하여 호출 할 수있는 방법이 있습니다.
피하십시오 async void
. 오류 처리에 대해 까다로운 의미가 있습니다. 나는 어떤 사람들이 그것을 "불과 잊는다"라고 부르는 것을 알고 싶습니다 나는 보통 "불과 충돌"이라는 표현을 사용합니다.
질문은 다음과 가변합니다. 동기 메서드 A ()가 주어지면 "이전 방식"보다 더 복잡한 솔루션을 얻지 않고 그대로 / 대기 방식을 사용하여 표현식으로 호출 할 수있는 방법
async
/ 는 필요하지 않습니다 await
. 다음과 같이 호출하십시오.
Task.Run(A);
다른 답변 과이 훌륭한 블로그 게시물 에서 언급했듯이 async void
UI 이벤트 처리기 외부에서 사용하는 것을 피하고 싶습니다 . 당신이 원하는 경우 안전 "화재와 잊지" async
방법이 패턴을 사용하는 것을 고려 (@ReedCopsey에 신용을,이 방법은 그가 채팅 대화 나에게 준 하나입니다) :
에 대한 확장 메서드를 만듭니다
Task
. 전달 된 것을 실행하고Task
모든 예외를 실행합니다.static async void FireAndForget(this Task task) { try { await task; } catch (Exception e) { // log errors } }
Task
스타일async
메서드를 만들 때 항상 사용하십시오async void
.다음과 같은 방법으로 메소드를 호출하십시오.
MyTaskAsyncMethod().FireAndForget();
필요하지 않습니다 await
( await
경고를 생성하지도 않습니다 ). 또한 모든 오류를 올바르게 처리 할 수 있으며 여기가 유일한 위치 async void
이므로 try/catch
모든 곳에 블록 을 두는 것을 기억할 필요가 없습니다 .
이것은 또한 당신이 실제로 그것을 일반적으로 원할 경우 "실행 후 잊어 버리기"방법으로 방법을 사용 하지 않는 옵션을 제공합니다 .async
await
나에게 어떤 것을 "기다리기"와 "불만 잊고"는 두 가지 직교 개념 인 것 같다. 메서드를 비동기 적으로 시작하고 결과를 신경 쓰지 않거나 작업이 완료된 후 원래 컨텍스트에서 실행을 재개하려고합니다 (그리고 반환 값을 사용할 수 있음). 이것이 바로 await가하는 일입니다. ThreadPool 스레드에서 메서드를 실행하고 싶다면 (UI가 차단되지 않도록)
Task.Factory.StartNew(() => DoIt2("Test2"))
그리고 당신은 괜찮을 것입니다.
제 생각에는 이러한 '실행 후 잊어 버리기'방법이 일련의 순차적 명령으로 논리를 작성할 수 있도록 UI와 백그라운드 코드를 인터리브하는 깔끔한 방법이 필요한 인공물이라는 것입니다. async / await는 SynchronizationContext를 통해 마샬링을 처리하므로 문제가되지 않습니다. 더 긴 시퀀스의 인라인 코드는 이전에 백그라운드 스레드의 루틴에서 시작되었던 '실행 후 잊어 버리기'블록이됩니다. 그것은 사실상 패턴의 반전입니다.
주요 차이점은 await 사이의 블록이 BeginInvoke보다 Invoke와 더 유사하다는 것입니다. BeginInvoke와 같은 동작이 더 필요한 경우 다음 비동기 메서드 (Task 반환)를 호출 한 다음 'BeginInvoke'하려는 코드가 나올 때까지 실제로 반환 된 Task를 기다리지 마십시오.
public async void Method()
{
//Do UI stuff
await SomeTaskAsync();
//Do more UI stuff (as if called via Invoke from a thread)
var nextTask = NextTaskAsync();
//Do UI stuff while task is running (as if called via BeginInvoke from a thread)
await nextTask;
}
참고 URL : https://stackoverflow.com/questions/12803012/fire-and-forget-with-async-vs-old-async-delegate
'ProgramingTip' 카테고리의 다른 글
정규식을 사용하여 후행 공백을 제거합니까? (0) | 2020.12.10 |
---|---|
전체 파일에서 열을 선택해야합니까? (0) | 2020.12.10 |
Remove () 메소드가 문자를 변수로 허용하는 이유는 무엇입니까? (0) | 2020.12.10 |
Excel의 수식에서 셀 번호가 증가하지 않도록 방지 (0) | 2020.12.10 |
소스에서 CentOS 6.5 / Linux / Unix에서 OpenSSL을 업그레이드하는 방법은 무엇입니까? (0) | 2020.12.10 |