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

간단한 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.

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

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



답변

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직접 사용하여 작성하는 것이 훨씬 더 어렵고 지저분합니다 . 또한 많은 상용구 코드를 제거하여 오류 처리 처리를 크게 단순화합니다.


답변

이 시도.

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

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


답변

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

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


답변