약속 스타일 작업에서는 시작을 호출 할 수 없습니다. 예외가오고있다


108

간단한 wpf 데스크톱 응용 프로그램을 만들고 있습니다. UI에는 .cs 파일에있는 버튼과 코드 만 있습니다.

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}

public void FunctionA()
{
    Task.Delay(5000).Start();
    MessageBox.Show("Waiting Complete");
}

그러나 놀랍게도 라인 Task.Delay(5000).Start();은 다음을 던지고 있습니다 InvalidOperationException.

약속 스타일 작업에서는 시작을 호출 할 수 없습니다.

아무도 왜 이런 일을 도울 수 있습니까?

답변:


171

Task클래스가 작업을 제공하기 전에 이미 시작 했기 때문에 해당 오류가 발생 합니다. Start생성자를 호출하여 생성 한 작업에 대해서만 호출해야하며 , 생성 할 때 작업을 시작하지 않을 설득력있는 이유가없는 한 그렇게해서는 안됩니다. 즉시 시작하려면을 사용 Task.Run하거나 Task.Factory.StartNew새로 만들고 시작 해야합니다 Task.

그래서, 이제 우리는 그 성가신 Start. 코드를 실행하면 메시지 상자가 5 초 후가 아니라 바로 표시된다는 것을 알게 될 것입니다. 그게 무슨 일입니까?

음, Task.Delay5 초 안에 완료 될 작업을 제공합니다. 5 초 동안 스레드 실행을 중지하지 않습니다. 원하는 것은 해당 작업이 완료된 후 실행되는 코드가있는 것입니다. 그게 ContinueWith목적입니다. 주어진 작업이 완료된 후 일부 코드를 실행할 수 있습니다.

public void FunctionA()
{
    Task.Delay(5000)
    .ContinueWith(t => 
    {
        MessageBox.Show("Waiting Complete");
    });
}

예상대로 작동합니다.

C # 5.0의 await키워드를 활용 하여 더 쉽게 연속을 추가 할 수도 있습니다.

public async Task FunctionA()
{
    await Task.Delay(5000);
    MessageBox.Show("Waiting Complete");
}

여기서 무슨 일이 벌어지고 있는지에 대한 전체 설명은이 질문의 범위를 벗어나지 만 최종 결과는 이전 방법과 매우 유사하게 작동하는 방법입니다. 메서드를 호출하면 5 초 후에 메시지 상자가 표시되지만 두 경우 모두 메서드 자체가 [거의] 즉시 반환됩니다. 즉, await매우 강력하고 간단하고 직관적 인 메서드를 작성할 수 있지만 ContinueWith직접 사용하여 작성하는 것이 훨씬 더 어렵고 지저분합니다 . 또한 많은 상용구 코드를 제거하여 오류 처리 처리를 크게 단순화합니다.


1

이 시도.

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}

public async void FunctionA()
{
    await Task.Delay(5000);
    MessageBox.Show("Waiting Complete");
}

-4

Servy가 말했듯이 작업이 이미 시작되었으므로 남은 작업은 기다리는 것뿐입니다 (.Wait ()) :

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}
public void FunctionA()
{
    Task.Delay(5000).Wait();
    MessageBox.Show("Waiting Complete");
}

1
Wait()작업을 호출 하면 작업이 해결 될 때까지 현재 스레드가 차단됩니다. 그것은 당신이 원하는 일이 거의 없습니다.
Jeremy

1
@Jeremy : 실제로 언급 한 동작에주의를 기울일 가치가 있지만,이 경우에는 그의 FunctionA가 이미 현재 스레드를 차단하고 있었기 때문에 작업이 언제 완료되었는지 확인할 방법을 찾고 있다고 가정했습니다. 대기와 비동기 (미래 독자를 위해)의 차이점을 명확히하려면이 링크
Sergiu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.