설명
Task 클래스는 반환 하지 않는 값을 지정 하 고는 일반적으로 단일 작업을 비동기적으로 실행 합니다. Task 개체는의 중앙 구성 요소 중 하나는 작업 기반 비동기 패턴 .NET Framework 4에서 처음 도입 된 합니다. 작업을 수행 하므로 Task 개체 일반적으로 비동기적으로 실행 스레드 풀 스레드에서 동기적으로 주 애플리케이션 스레드에서 사용할 수 있습니다 것이 아니라 합니다 Status 속성인 뿐만 IsCanceled, IsCompleted, 및 IsFaulted 속성에는 작업의 상태를 확인 합니다. 가장 일반적으로 작업을 수행 하는 작업을 지정 하는 람다 식 사용 됩니다.
사용할 값을 반환 하는 작업의 경우는 Task<TResult> 클래스입니다.
using System;
using System.Threading;
using System.Threading.Tasks;
class Example
{
static void Main()
{
Action<object> action = (object obj) =>
{
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, obj,
Thread.CurrentThread.ManagedThreadId);
};
// Create a task but do not start it.
Task t1 = new Task(action, "alpha");
// Construct a started task
Task t2 = Task.Factory.StartNew(action, "beta");
// Block the main thread to demonstrate that t2 is executing
t2.Wait();
// Launch t1
t1.Start();
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
// Wait for the task to finish.
t1.Wait();
// Construct a started task using Task.Run.
String taskData = "delta";
Task t3 = Task.Run( () => {Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, taskData,
Thread.CurrentThread.ManagedThreadId);
});
// Wait for the task to finish.
t3.Wait();
// Construct an unstarted task
Task t4 = new Task(action, "gamma");
// Run it synchronously
t4.RunSynchronously();
// Although the task was run synchronously, it is a good practice
// to wait for it in the event exceptions were thrown by the task.
t4.Wait();
}
}
// The example displays output like the following:
// Task=1, obj=beta, Thread=3
// t1 has been launched. (Main Thread=1)
// Task=2, obj=alpha, Thread=4
// Task=3, obj=delta, Thread=3
// Task=4, obj=gamma, Thread=1
분리 작업 만들기 및 실행
Task 클래스는 또한 작업을 초기화 하는 하지만 해당 실행에 대 한 예약 하지 않습니다 하는 생성자를 제공 합니다. 성능상의 이유로 합니다 Task.Run 또는 TaskFactory.StartNew 메서드를 만들고 계산 태스크를 예약 하기 위한 기본 메커니즘입니다 하지만 생성 및 일정 예약을 구분 해야 합니다는 시나리오에 대 한 생성자를 사용 하 여를 호출 합니다 Task.Start 나중에 실행에 대 한 작업을 예약 하는 방법입니다.
하나 이상의 작업이 완료 되기를 기다리는
작업 일반적으로 스레드 풀 스레드에서 비동기적으로 실행, 때문에 작업을 인스턴스화해야 하는 즉시 만들고 작업을 시작 하는 스레드 실행을 계속 합니다. 일부 경우에 호출 스레드는 주 애플리케이션 스레드의 경우 앱을 종료할 수 있습니다 보다 먼저 태스크 실제로 실행을 시작 합니다. 다른 애플리케이션의 논리는 하나 이상의 작업 실행을 완료 하는 경우에 호출 스레드가 계속 실행 필요할 수 있습니다. 호출 스레드의 실행을 동기화 할 수 있습니다 및 비동기 작업이 출시를 호출 하 여를 Wait 메서드를 하나 이상의 작업이 완료 될 때까지 기다립니다.
완료 하는 단일 작업에 대 한 대기를 호출 하면 해당 Task.Wait 메서드. 에 대 한 호출을 Wait 메서드는 단일 클래스 인스턴스 실행이 완료 될 때까지 호출 스레드를 차단 합니다.
다음 예제에서는 매개 변수가 없는 호출 Wait() 작업이 완료 될 때까지 무조건 대기 하는 방법입니다. 태스크를 호출 하 여 작업을 시뮬레이트하는 Thread.Sleep 2 초 대기 하는 방법입니다.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static Random rand = new Random();
static void Main()
{
// Wait on a single task with no timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
Console.WriteLine("taskA Status: {0}", taskA.Status);
try {
taskA.Wait();
Console.WriteLine("taskA Status: {0}", taskA.Status);
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// taskA Status: WaitingToRun
// taskA Status: RanToCompletion
또한 조건에 따라 작업이 완료 되기를 기다릴 수 있습니다. 합니다 Wait(Int32) 및 Wait(TimeSpan) 메서드는 작업이 완료 될 때까지 호출 스레드를 차단 또는 먼저 도달 하는 시간 제한 간격이 경과 합니다. 다음 예제에서는 2 초 동안 대기 하지만 해당 호출 스레드는 차단 시간 제한이 만료 될 때까지 1 초 제한 시간 값을 정의 하는 작업을 시작 하므로 전과 작업 실행이 완료 합니다.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Wait on a single task with a timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
try {
taskA.Wait(1000); // Wait for 1 second.
bool completed = taskA.IsCompleted;
Console.WriteLine("Task A completed: {0}, Status: {1}",
completed, taskA.Status);
if (! completed)
Console.WriteLine("Timed out before task A completed.");
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// Task A completed: False, Status: Running
// Timed out before task A completed.
호출 하 여 취소 토큰을 제공할 수도 있습니다는 Wait(CancellationToken) 고 Wait(Int32, CancellationToken) 메서드. 경우 토큰의 IsCancellationRequested 속성은 true 는 더 이상 true 하는 동안 합니다 Wait 메서드를 실행, 메서드가 throw는 OperationCanceledException합니다.
경우에 따라 대기 하려는 싶지만 완료 하는 일련의 작업을 실행 중 첫 번째 작업 하는 주의 해야입니다. 이 위해 수 중 하나를 호출의 오버 로드는 Task.WaitAny 메서드. 다음 예제에서는 난수 생성기에서 간격 결정에 대 한 절전 모드로 전환 되는 각 세 가지 작업을 만듭니다. WaitAny(Task[]) 메서드 첫 번째 작업이 완료 되기를 기다립니다. 다음 예제에서는 세 작업의 상태에 대 한 정보를 표시합니다.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var tasks = new Task[3];
var rnd = new Random();
for (int ctr = 0; ctr <= 2; ctr++)
tasks[ctr] = Task.Run( () => Thread.Sleep(rnd.Next(500, 3000)));
try {
int index = Task.WaitAny(tasks);
Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
Console.WriteLine("Status of all tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
catch (AggregateException) {
Console.WriteLine("An exception occurred.");
}
}
}
// The example displays output like the following:
// Task #1 completed first.
//
// Status of all tasks:
// Task #3: Running
// Task #1: RanToCompletion
// Task #4: Running
일련의 작업을 호출 하 여 완료 모든 않을 수도 있습니다는 WaitAll 메서드. 다음 예제에서는 10 개의 작업을 만드는, 대기를 완료 하려면 모든 10에 대 한 다음 해당 상태를 표시 합니다.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Wait for all tasks to complete.
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => Thread.Sleep(2000));
}
try {
Task.WaitAll(tasks);
}
catch (AggregateException ae) {
Console.WriteLine("One or more exceptions occurred: ");
foreach (var ex in ae.Flatten().InnerExceptions)
Console.WriteLine(" {0}", ex.Message);
}
Console.WriteLine("Status of completed tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
}
// The example displays the following output:
// Status of completed tasks:
// Task #2: RanToCompletion
// Task #1: RanToCompletion
// Task #3: RanToCompletion
// Task #4: RanToCompletion
// Task #6: RanToCompletion
// Task #5: RanToCompletion
// Task #7: RanToCompletion
// Task #8: RanToCompletion
// Task #9: RanToCompletion
// Task #10: RanToCompletion
하나 이상의 작업이 완료 되기를 기다릴 때 호출 하는 스레드에서 실행 중인 작업에서 throw 된 예외 전파는 참고를 Wait 메서드를 다음 예제와 같이 합니다. 정상적으로 완료 중 3 개는 12 작업 및 세 가지 예외는 throw를 시작 합니다. 나머지 6 개 작업 중 세 개는 시작 하기 전에 취소 되 고 3은 실행 중에 취소 됩니다. 예외가 throw 되는 WaitAll 에 의해 처리 되며 메서드 호출을 try / catch 블록입니다.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Create a cancellation token and cancel it.
var source1 = new CancellationTokenSource();
var token1 = source1.Token;
source1.Cancel();
// Create a cancellation token for later cancellation.
var source2 = new CancellationTokenSource();
var token2 = source2.Token;
// Create a series of tasks that will complete, be cancelled,
// timeout, or throw an exception.
Task[] tasks = new Task[12];
for (int i = 0; i < 12; i++)
{
switch (i % 4)
{
// Task should run to completion.
case 0:
tasks[i] = Task.Run(() => Thread.Sleep(2000));
break;
// Task should be set to canceled state.
case 1:
tasks[i] = Task.Run( () => Thread.Sleep(2000),
token1);
break;
case 2:
// Task should throw an exception.
tasks[i] = Task.Run( () => { throw new NotSupportedException(); } );
break;
case 3:
// Task should examine cancellation token.
tasks[i] = Task.Run( () => { Thread.Sleep(2000);
if (token2.IsCancellationRequested)
token2.ThrowIfCancellationRequested();
Thread.Sleep(500); }, token2);
break;
}
}
Thread.Sleep(250);
source2.Cancel();
try {
Task.WaitAll(tasks);
}
catch (AggregateException ae) {
Console.WriteLine("One or more exceptions occurred:");
foreach (var ex in ae.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message);
}
Console.WriteLine("\nStatus of tasks:");
foreach (var t in tasks) {
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
if (t.Exception != null) {
foreach (var ex in t.Exception.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name,
ex.Message);
}
}
}
}
// The example displays output like the following:
// One or more exceptions occurred:
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
//
// Status of tasks:
// Task #13: RanToCompletion
// Task #1: Canceled
// Task #3: Faulted
// NotSupportedException: Specified method is not supported.
// Task #8: Canceled
// Task #14: RanToCompletion
// Task #4: Canceled
// Task #6: Faulted
// NotSupportedException: Specified method is not supported.
// Task #7: Canceled
// Task #15: RanToCompletion
// Task #9: Canceled
// Task #11: Faulted
// NotSupportedException: Specified method is not supported.
// Task #12: Canceled
작업 기반 비동기 작업에서 예외 처리에 대 한 자세한 내용은 참조 하세요. 예외 처리합니다.
* 참고 https://docs.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task?view=netframework-4.8