Về việc sử dụng Task.Start (), Task.Run () và Task.Factory.StartNew ()


143

Tôi chỉ thấy 3 thói quen liên quan đến việc sử dụng TPL làm cùng một công việc; đây là mã:

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Create a task and supply a user delegate by using a lambda expression. 
    Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
    // Start the task.
    taskA.Start();

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                  Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Define and run the task.
    Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                      Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Better: Create and start the task in one operation. 
    Task taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                    Thread.CurrentThread.Name);

    taskA.Wait();                  
}

Tôi chỉ không hiểu tại sao MS cung cấp cho 3 cách khác nhau để chạy các công việc trong TPL vì chúng đều hoạt động như nhau: Task.Start(), Task.Run()Task.Factory.StartNew().

Tell Me, đang Task.Start(), Task.Run()Task.Factory.StartNew()tất cả sử dụng cho cùng một mục đích hay họ có ý nghĩa khác nhau?

Khi nào nên sử dụng Task.Start(), khi nào nên sử dụng Task.Run()và khi nào nên sử dụng Task.Factory.StartNew()?

Xin hãy giúp tôi hiểu cách sử dụng thực tế của họ theo kịch bản rất chi tiết với các ví dụ, cảm ơn.


có một bài viết cũ giải thích rằng ở đâyở đây cho cái mới hơnTask.Run - có thể điều này sẽ trả lời câu hỏi của bạn;)
Carsten

Dưới đây là một ví dụ về nơi Task.Startthực sự hữu ích.
noseratio

Câu trả lời:


171

Task.Runlà một cách viết tắt cho Task.Factory.StartNewcác đối số an toàn cụ thể:

Task.Factory.StartNew(
    action, 
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

Nó đã được thêm vào .Net 4.5 để giúp sử dụng asyncvà giảm tải công việc ngày càng thường xuyên cho ThreadPool.

Task.Factory.StartNew(được thêm bằng TPL trong .Net 4.0) mạnh mẽ hơn nhiều. Bạn chỉ nên sử dụng nó nếu Task.Runkhông đủ, ví dụ như khi bạn muốn sử dụng TaskCreationOptions.LongRunning(mặc dù không cần thiết khi đại biểu không đồng bộ. Thêm vào đó trên blog của tôi: LongRicky là vô dụng cho nhiệm vụ.Run With async-await ). Thông tin thêm về Task.Factory.StartNewtrong Task.Run vs Task.Factory.StartNew

Đừng bao giờ tạo Taskvà gọi Start()trừ khi bạn tìm thấy một lý do cực kỳ tốt để làm như vậy. Nó chỉ nên được sử dụng nếu bạn có một số phần cần tạo tác vụ nhưng không lên lịch cho chúng và phần khác lên lịch mà không tạo. Đó gần như không bao giờ là một giải pháp thích hợp và có thể nguy hiểm. Thông tin khác trong "Nhiệm vụ.Factory.StartNew" so với "Nhiệm vụ mới (...). Bắt đầu"

Tóm lại, chủ yếu là sử dụng Task.Run, sử dụng Task.Factory.StartNewnếu bạn phải và không bao giờ sử dụng Start.


5
u đã nói "Đừng bao giờ tạo một tác vụ và gọi Start ()" chuyển hướng tôi đến bất kỳ bài viết hay nào sẽ cho thấy điều đó có thể gây ra bởi Task.Start (). Tôi cần chi tiết bởi vì bạn nói để tránh nó. cảm ơn đã trả lời
Mou


1
@Mou Task.Startcó vị trí của nó để kế thừa các loại chủ yếu.
Yuval Itzchakov

1
@Mou Nó không hiệu quả vì nó yêu cầu đồng bộ hóa để đảm bảo rằng nó chỉ được gọi một lần. Các tùy chọn khác thì không.
i3arnon

2
@Mou Bạn có lẽ nên đọc bài giải thích vấn đề này blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

Câu trả lời ngắn gọn :

Nếu bạn không sử dụng các tác vụ của trẻ em lồng nhau và luôn muốn các tác vụ của mình được thực thi trên Thread Pool thì tốt hơn là sử dụng Task.Run.

Câu trả lời dài:

Task.RunTask.Factory.StartNewcả hai đều cung cấp hỗ trợ cho việc tạo và lập lịch các đối tượng Nhiệm vụ, vì vậy chúng tôi không cần tạo Taskvà gọiStart()

Task.Run(action);

Tương đương với:

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

Task.Factory.StartNew(action);

Tương đương với:

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);

Task.Runsử dụng TaskCreationOptions.DenyChildAttachđiều đó có nghĩa là các nhiệm vụ của trẻ em không thể được gắn vào cha mẹ và nó sử dụng TaskScheduler.Defaultđiều đó có nghĩa là nhiệm vụ chạy các nhiệm vụ trên Thread Pool sẽ luôn được sử dụng để chạy các tác vụ.

Task.Factory.StartNewsử dụng TaskScheduler.Currentcó nghĩa là lịch trình của luồng hiện tại, nó có thể TaskScheduler.Defaultnhưng không phải luôn luôn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.