[C#] UI 스레드에서 작업 계속

초기 작업이 생성 된 스레드에서 작업 계속을 실행하도록 지정하는 ‘표준’방법이 있습니까?

현재 아래 코드가 있습니다. 작동하지만 디스패처를 추적하고 두 번째 액션을 만드는 것은 불필요한 오버 헤드처럼 보입니다.

dispatcher = Dispatcher.CurrentDispatcher;
Task task = Task.Factory.StartNew(() =>
{
    DoLongRunningWork();
});

Task UITask= task.ContinueWith(() =>
{
    dispatcher.Invoke(new Action(() =>
    {
        this.TextBlock1.Text = "Complete"; 
    }
});



답변

다음과 같이 연속을 호출하십시오 TaskScheduler.FromCurrentSynchronizationContext().

    Task UITask= task.ContinueWith(() =>
    {
     this.TextBlock1.Text = "Complete"; 
    }, TaskScheduler.FromCurrentSynchronizationContext());

현재 실행 컨텍스트가 UI 스레드에있는 경우에만 적합합니다.


답변

비동기를 사용하면 다음과 같이 할 수 있습니다.

await Task.Run(() => do some stuff);
// continue doing stuff on the same context as before.
// while it is the default it is nice to be explicit about it with:
await Task.Run(() => do some stuff).ConfigureAwait(true);

하나:

await Task.Run(() => do some stuff).ConfigureAwait(false);
// continue doing stuff on the same thread as the task finished on.


답변

반환 값이 있으면 UI로 보내야하며 다음과 같이 일반 버전을 사용할 수 있습니다.

필자의 경우 MVVM ViewModel에서 호출됩니다.

var updateManifest = Task<ShippingManifest>.Run(() =>
    {
        Thread.Sleep(5000);  // prove it's really working!

        // GenerateManifest calls service and returns 'ShippingManifest' object 
        return GenerateManifest();  
    })

    .ContinueWith(manifest =>
    {
        // MVVM property
        this.ShippingManifest = manifest.Result;

        // or if you are not using MVVM...
        // txtShippingManifest.Text = manifest.Result.ToString();    

        System.Diagnostics.Debug.WriteLine("UI manifest updated - " + DateTime.Now);

    }, TaskScheduler.FromCurrentSynchronizationContext());


답변

이 유용한 스레드이기 때문에이 버전을 추가하고 싶었고 이것이 매우 간단한 구현이라고 생각합니다. 멀티 스레드 응용 프로그램 인 경우이 유형을 여러 유형으로 여러 번 사용했습니다.

 Task.Factory.StartNew(() =>
      {
        DoLongRunningWork();
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
              { txt.Text = "Complete"; }));
      });


답변

Task.Run 호출에 들어간 후 ui 스레드에서 작업을 수행하는 좋은 방법을 찾고 있었기 때문에 Google을 통해 여기에 도달했습니다. 다음 코드를 사용 await하면 UI 스레드로 다시 돌아갈 수 있습니다 .

나는 이것이 누군가를 돕기를 바랍니다.

public static class UI
{
    public static DispatcherAwaiter Thread => new DispatcherAwaiter();
}

public struct DispatcherAwaiter : INotifyCompletion
{
    public bool IsCompleted => Application.Current.Dispatcher.CheckAccess();

    public void OnCompleted(Action continuation) => Application.Current.Dispatcher.Invoke(continuation);

    public void GetResult() { }

    public DispatcherAwaiter GetAwaiter()
    {
        return this;
    }
}

용법:

... code which is executed on the background thread...
await UI.Thread;
... code which will be run in the application dispatcher (ui thread) ...


답변