Programming/.NET

Task는 비동기 호출에 사용될 수 있습니다.

 

static void Main(string[] args)
{
    Task t = new Task(() => {
        getMyData();
    });
    t.Start();

    Console.WriteLine("현재 스레드 완료");
    Console.Read();
}

static void getMyData()
{
    using (FileStream fs = new FileStream("test.txt"FileMode.OpenFileAccess.ReadFileShare.None)) {
        byte[] b = new byte[fs.Length];
        fs.Read(b, 0, b.Length);

        string s = Encoding.UTF8.GetString(b);
        Console.WriteLine(s);
    }
}

 

Task는 Action타입의 델리게이트를 매개변수로 받으므로 여기에 작업항목을 지정하고 Start 메서드를 호출하면 ThreadPool의 여유스레드를 통해 내부 코드를 비동기로 수행하게 됩니다.

 

기본이 비동기이므로 작업진행과 완료가 따로 처리되겠지만 만약 완료시까지 다음 실행을 대기시켜야 한다면 Start 호출이 후 Wait 메서드를 호출해야 합니다.

 

static void Main(string[] args)
{
    Task<string> t = new Task<string>(() => {
        return getMyData();
    });
    t.Start();

    Console.WriteLine("현재 스레드 완료");

    Console.WriteLine(t.Result);
    Console.Read();
}

static string getMyData()
{
    using (FileStream fs = new FileStream("test.txt"FileMode.OpenFileAccess.ReadFileShare.None)) {
        byte[] b = new byte[fs.Length];
        fs.Read(b, 0, b.Length);

        string s = Encoding.UTF8.GetString(b);

        return s;
    }
}

 

Task는 반환값이 없는 경우 사용되며 특정 값을 반환받는 경우라면 Task<T>형식을 사용해야 합니다. 이때는 결과값을 갖는 Func 타입의 델리게이트를 매개변수로 넘겨야 합니다. 그리고 받은 값은 t.Result로 가져올 수 있습니다.

 

static void Main(string[] args)
{
    Task.Factory.StartNew(() => { getWebData();  });

    Console.WriteLine("현재 스레드 완료");
    Console.Read();
}

static void getMyData()
{
    using (FileStream fs = new FileStream("test.txt"FileMode.OpenFileAccess.ReadFileShare.None)) {
        byte[] b = new byte[fs.Length];
        fs.Read(b, 0, b.Length);

        string s = Encoding.UTF8.GetString(b);
        Console.WriteLine(s);
    }
}

 

Task는 일일이 객체를 생성할 필요없이 Factory의 StartNew메서드를 사용하여 작업을 비동기로 수행할 수 있습니다.

 

static void Main(string[] args)
{
    Task<string> T = Task.Factory.StartNew(() => { return getMyData();  });

    Console.WriteLine("현재 스레드 완료");

    Console.WriteLine(T.Result);
    Console.Read();
}

static string getMyData()
{
    using (FileStream fs = new FileStream("test.txt"FileMode.OpenFileAccess.ReadFileShare.None)) {
        byte[] b = new byte[fs.Length];
        fs.Read(b, 0, b.Length);

        string s = Encoding.UTF8.GetString(b);
        return s;
    }
}

 

물론 값을 가져오는 경우에도 구현이 가능합니다.

 

이렇게 Task를 사용해 비동기호출로 코드를 실행하는 방식은 심지어 비동기 호출에 사용되는 async / await를 지원하지 않는 메서드에도 async / await를 사용할 수 있는 방법을 제공합니다.

 

static void Main(string[] args)
{
    callMethod();
    Console.WriteLine("현재 스레드 완료");
    Console.Read();
}

static async void callMethod()
{
    string s = await getFileData();
    Console.WriteLine(s);
}

static Task<stringgetFileData()
{
    return Task.Factory.StartNew(() => { return getMyData()});
}

static string getMyData()
{
    using (FileStream fs = new FileStream("test.txt"FileMode.OpenFileAccess.ReadFileShare.None)) {
        byte[] b = new byte[fs.Length];
        fs.Read(b, 0, b.Length);

        string s = Encoding.UTF8.GetString(b);
        return s;
    }
}

 

async / await에서 await는 Task타입을 반환받는 메서드에만 사용할 수 있으므로 Task 형식을 반환하는 메서드를 임의로 구현한 뒤에 해당 메서드를 호출할때 await를 붙여주기만 하면 됩니다.

'Programming > .NET' 카테고리의 다른 글

[C#] ArrayList  (0) 2017.11.14
[C#] 선택적 매개변수  (0) 2017.11.07
[C#] Task  (0) 2017.11.01
[C#] BigInteger  (0) 2017.10.24
[ASP.NET MVC] 다중 모델 사용하기 (Tuple)  (0) 2017.10.18
[C#] dynamic 과 덕 타이핑(duck typing)  (0) 2017.10.10
0 0