Programing

C #에서 비동기 / 대기 이해

lottogame 2020. 11. 12. 07:39
반응형

C #에서 비동기 / 대기 이해


C # 5.0에서 async / await에 대해 배우기 시작했는데 전혀 이해하지 못합니다. 병렬 처리에 어떻게 사용할 수 있는지 이해하지 못합니다. 다음과 같은 매우 기본적인 프로그램을 시도했습니다.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task task1 = Task1();
            Task task2 = Task2();

            Task.WaitAll(task1, task2);

            Debug.WriteLine("Finished main method");
        }

        public static async Task Task1()
        {
            await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
            Debug.WriteLine("Finished Task1");
        }

        public static async Task Task2()
        {
            await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
            Debug.WriteLine("Finished Task2");
        }

    }
}

이 프로그램은 호출을 차단 Task.WaitAll()하고 끝나지 않지만 이유를 이해하지 못합니다. 나는 단순한 것을 놓치고 있거나 이것에 대한 올바른 정신적 모델을 가지고 있지 않다고 확신하며 거기에 나와있는 블로그 또는 MSDN 기사가 도움이되지 않습니다.


/에 대한 소개부터asyncawait 시작 하여 TAP에 대한 공식 MSDN 문서에 대한 후속 조치를 취하는 것이 좋습니다 .

내 소개 블로그 게시물에서 언급했듯이 TaskTPL에서 보류되고 순수 async코드 에서 사용되지 않는 여러 구성원이 있습니다 . new Task그리고 Task.Start교체되어야 Task.Run(또는 TaskFactory.StartNew). 마찬가지로, Thread.Sleep교체되어야한다 Task.Delay.

마지막으로, 사용하지 않는 것이 좋습니다 Task.WaitAll. 콘솔 응용 프로그램은해야 Wait하나에서와 Task하는 용도 Task.WhenAll. 이러한 모든 변경 사항으로 코드는 다음과 같습니다.

class Program
{
    static void Main(string[] args)
    {
        MainAsync().Wait();
    }

    public static async Task MainAsync()
    {
        Task task1 = Task1();
        Task task2 = Task2();

        await Task.WhenAll(task1, task2);

        Debug.WriteLine("Finished main method");
    }

    public static async Task Task1()
    {
        await Task.Delay(5000);
        Debug.WriteLine("Finished Task1");
    }

    public static async Task Task2()
    {
        await Task.Delay(10000);
        Debug.WriteLine("Finished Task2");
    }
}

C # 작업, 비동기 및 대기 이해

C # 작업

작업 클래스는 비동기 작업 래퍼입니다. Thread.Sleep (1000)은 1 초 동안 실행중인 스레드를 중지 할 수 있습니다. Task.Delay (1000)는 현재 작업을 중지하지 않습니다. 코드 참조 :

public static void Main(string[] args){
    TaskTest();
}
private static void TaskTest(){
     Task.Delay(5000);
     System.Console.WriteLine("task done");
}

When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.

Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.

async and await

Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await

public static void Main(string[] args){
     TaskTest();
     System.Console.WriteLine("main thread is not blocked");
     Console.ReadLine();
}
private static async void TaskTest(){
     await Task.Delay(5000);
     System.Console.WriteLine("task done");
}

async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.

Cancel a Task

Since Task is a state machine, there must be a way to cancel the task while task is in running.

static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
    TaskTest();
    System.Console.WriteLine("main thread is not blocked");
    var input=Console.ReadLine();
    if(input=="stop"){
          tokenSource.Cancel();
          System.Console.WriteLine("task stopped");
     }
     Console.ReadLine();
}
private static async void TaskTest(){
     try{
          await Task.Delay(5000,tokenSource.Token);
     }catch(TaskCanceledException e){
          //cancel task will throw out a exception, just catch it, do nothing.
     }
     System.Console.WriteLine("task done");
}

Now, when the program is in running, you can input "stop" to cancel the Delay task.


Your tasks never finish because they never start running.

I would Task.Factory.StartNew to create a task and start it.

public static async Task Task1()
{
  await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
  Debug.WriteLine("Finished Task1");
}

public static async Task Task2()
{
  await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
  Debug.WriteLine("Finished Task2");
}

As a side note, if you're really just trying to pause in a async method, there's no need to block an entire thread, just use Task.Delay

public static async Task Task1()
{
  await Task.Delay(TimeSpan.FromSeconds(5));
  Debug.WriteLine("Finished Task1");
}

public static async Task Task2()
{
  await Task.Delay(TimeSpan.FromSeconds(10));
  Debug.WriteLine("Finished Task2");
}

Async and await are markers which mark code positions from where control should resume after a task (thread) completes. Here's a detail youtube video which explains the concept in a demonstrative manner http://www.youtube.com/watch?v=V2sMXJnDEjM

If you want you can also read this coodeproject article which explains the same in a more visual manner. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”and“Await”(Codemarkers)

참고URL : https://stackoverflow.com/questions/14177891/understanding-async-await-in-c-sharp

반응형