소켓에서 읽기를 반복하는 작업이 있습니다.
private async void readLoop() {
while (!cts.IsCancelRequested()) {
await socket.ReceiveAsync(data, ...);
doWork(data);
}
}
그리고 작업이 생성되는 즉시 실행할 필요가 없으므로Task
생성자보다는Task.Run
.
private Task readTask = new Task(readLoop, cts, LongRunning);
// when the task need to run:
readTask.Start()
이 시점에서 그것은 잘 작동합니다. 단, 작업이 끝나야 할 때, 전화 할 때readTask.Wait()
또는await readTask
, 예외는에서 일어났다ReceiveAsync
또는doWork
에 붙어 있지 않다.readTask
. 즉 심지어 예외가 있었음을 의미합니다.readTask.Status
~이다.RunToComplete
과readTask.Exception
~이다.null
. 일치. 워드 프로세서, 비동기 메서드는 무효 반환하기 때문에 때문입니다. 그러나이 시도 할 때 :
private async Task readLoop() {...}
컴파일되지 않습니다.
error CS0407: 'Task WebSocketInitiator.readLoop()' has the wrong return type
어쨌든 나중에 작업을 시작하게하고 동시에 작업에서 발생한 예외를 추적합니까?
문제를 보여줄 수있는 최소한의 테스트 케이스 :https://dotnetfiddle.net/JIfDIn
만약 당신이 올바르게 이해한다면, 필요할 때까지 작업을 연기하고 싶지만 생성자에서 생성을 유지하고 싶을 것입니다. 괜찮습니다. 이러한 상황에 사용되는 패턴이 있습니다. 그것은 ~라고 불린다Lazy
.
그러나 Lazy는 비동기 적이 아닙니다.그러나 Stephen Taub는 AsyncLazy라고하는 비동기 구현을 만들었습니다.
생성 한 외부 작업에 대한 반환 값을 지정하지 않았기 때문에 오류 메시지가 나타나는 이유가 있습니다. 또한 돌아올 필요가있다.foo
s 값. 내부 태스크를 반환하는 람다 (lambda)에서 호출을 랩핑하면 다음과 같이 얻을 수 있습니다.
var task1 = new Task<Task>(async () => await foo(),
CancellationToken.None, TaskCreationOptions.LongRunning);
task1.Start();
그러나 당신이 그것을 기다리고있을 때 당신은 바깥의 일을 기다리고 그것을 돌려주는 일을 기다리지 않을 것이다. 따라서 그것을 언랩해야합니다 :
task1.Unwrap().Wait();
이렇게하면 예외를 잡을 수 있습니다. 하나,이것은 아마도가장 좋은 방법은 Task.Run, async 및 await을 사용하는 전체 이유가 이러한 구성을 피하는 것이었기 때문입니다. 결론적으로:
task1
- Kevin Gosse.Start()
을 (를) 호출 할 수 없습니다. - Default
그리고 작업이 생성되는 즉시 실행될 필요가 없으므로 Task.Run 대신 Task 생성자를 사용하고 있습니다.
작업 생성자는 절대로 사용하지 않아야합니다.말 그대로 합리적인 유스 케이스가 있습니다.조금도.
귀하의 경우에는 위임이나 지연 초기화가 필요하지 않은 것처럼 들리지만, 멤버와 메서드는 비공개이므로 작업이 실행될 때 작업 멤버를 할당하는 것이 중요합니다.
private async Task readLoop();
// when the task needs to run:
readTask = Task.Run(() => readLoop());
그러나,해야 할 것미래에 실행될 코드를 표현해야하며 현재는 그렇지 않습니다. 그러면 대리인이 필요합니다. 이 경우,비동기 대리인:Func<Task>
:
Func<Task> func = () => Task.Run(() => readLoop());
...
Task task = func();
async
메소드 반환void
, 이것은 호출 코드가 예외를 관찰하지 못하도록합니다.Task
예외를 나타낼 수있는 메소드 너는 사용해서는 안된다.async void
이런 맥락에서, 그렇게하지 않는 것이 바람직한 습관을 따랐 으면, 당신의 문제는 일어나지 않을 것입니다. 왜 반환 유형을 변경할 때 CS0407을 얻을 수 있습니까? 다른 곳에서도 실수를 저질렀어야했는데 좋은 물건을 제공하지 못했습니다.최소, 완료 및 확인 가능한 예제문제가 확실하게 재현되어 문제가 무엇인지 아무도 말할 수 없습니다. - Peter Duniho