2013-08-20 1 views
0

내 Winforms 응용 프로그램에서 작업을 시작할 때 비동기 적으로 수행되거나 수행되지 않을 수 있습니다. 작업이 모두 동 기적으로 완료되는 경우 작업이 비동기 적으로 완료 될 때 사용하는 것과 동일한 방법을 사용하여 대기 커서를 표시 할 수 없습니다. 이 예에서모든 작업이 동기 일 때 대기 커서 표시

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     var t = ButtonClick(button1, DoWorkAsync1); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     var t = ButtonClick(button2, DoWorkAsync2); 
    } 

    private async Task ButtonClick(Button btn, Func<Task> doWorkAsync) 
    { 
     // Disable the UI and show the wait cursor 
     btn.Text = "Working..."; 
     btn.Enabled = false; 
     UseWaitCursor = true; 

     // Application.DoEvents(); // Inserting this causes the problem to go away. 
     await doWorkAsync(); 

     // Simulate an update of the UI taking a long time 
     Thread.Sleep(2000); 

     // Renable the UI and stop showing the wait cursor 
     UseWaitCursor = false; 
     btn.Enabled = true; 
    } 

    private Task DoWorkAsync1() 
    { 
     // Work takes some time 
     return Task.Delay(2000); 
    } 

    private Task DoWorkAsync2() 
    { 
     // Work doesn't take any time, results are immediately available 
     return Task.FromResult<int>(0); 
    } 
} 

:

다음은 문제를 보여주는 예입니다

  • (작업이 비동기 적으로 수행되기 때문에) 대기 커서를 보여 않습니다 Button1을 클릭.
  • button2를 클릭하면 이 아닌이 대기 커서를 표시합니다 (작업이 모두 동 기적으로 완료되기 때문에).
  • button1과 button2를 클릭하면 UI가 예상대로 비활성화됩니다.

button1 또는 button2를 클릭하면 버튼을 클릭하고 UI 업데이트 작업이 완료되는 사이의 전체 간격 동안 대기 커서가 표시되어야합니다.

질문 :

  • Application.DoEvent (발생하는 펌핑 메시지를 야기하거나 아무것도 상당)를 삽입하지 않고이 문제를 해결하는 방법이 있나요, 아니면 메시지를 펌핑에 의해서만 가능하다.
  • 제쳐두고 : 왜 컨트롤의 사용이 올바르게 작동하지 않습니까? (커서와 다름).
+1

가능한 중복 HTTP :

또는 당신은 단지 직접 동 기적으로 실행되지 않도록 doWorkAsync에 계속 추가 할 수 : //stackoverflow.com/questions/302663/cursor-current-vs-this-cursor-in-net-c) –

+0

@HansPassant, 고마워요 - 그 대답은 : UseWaitCursor는 WM_SETCURSOR 메시지를 기다리고 있습니다. 이 솔루션은 나를 위해 작동합니다. –

+0

@MattSmith SetCursor는 사용자 정의 커서 나 표준 커서를 표시하는 데 도움이됩니다. '대기 커서'는 매우 사소한 것입니다. –

답변

0

당신이 백그라운드 스레드에서 수행 할 동기 일이 있으면 Task.Run 다음 await 결과 (호출 코드가 비동기로 취급)에 문의하십시오. 당신의 동기 작업은 정말 즉시, 그리고 당신이 정말로 다른 UI 작업을하기 전에 몇 가지 UI 업데이트 (예를 들어, 커서)를 적용 할 경우

private Task DoWorkAsync1() 
{ 
    return Task.Delay(2000); 
} 

private Task DoWorkAsync2() 
{ 
    return Task.Run(() => Thread.Sleep(2000)); 
} 

또는, 당신은 단지이 작업을 수행 할 수 있습니다

await Task.Delay(10); 
+0

백그라운드 스레드에서 동기 작업을하고 싶지 않습니다. –

+0

정말 2 초의 UI 작업이 필요한 경우 시간이 오래 걸립니다. 마법은 없습니다. –

+0

나는 어떤 마법도 원하지 않는다 - 나는 그 2 초 동안 대기 커서를 보여주고 싶다. –

0

대신 DoEvents 던져에서 :

await Task.Run(() => { }); 

가 시작될 때 방법의 나머지 RU 될 수 있도록이의 기다려온 작업이 바로 완료되지 않도록한다 n을 동기식이 아닌 연속으로 사용합니다.

await doWorkAsync 
    .ContinueWith(t => { }, TaskContinuationOptions.HideScheduler); 
[닷넷에서 this.Cursor 대 Cursor.Current (C 번호)] (의
+0

왜 '기다릴 Task.Yield()'? – svick

+0

@svick 몇 가지 테스트를 실시했지만 작동하지 않았습니다. 그것은 내가 무엇을해야했는지에 대한 나의 첫 번째 생각이었다. – Servy

+0

빈 스레드 풀 작업은 비 결정적으로 쉽게 인라인 될 수 있습니다. 수율은 왜 효과가 없습니까? 이상한. – usr

관련 문제