เกี่ยวกับการใช้งานของ Task.Start (), Task.Run () และ Task.Factory.StartNew ()


143

ฉันเพิ่งเห็น 3 กิจวัตรเกี่ยวกับการใช้ TPL ซึ่งทำงานเหมือนกัน นี่คือรหัส:

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();                  
}

ผมก็ไม่เข้าใจว่าทำไม MS ให้ 3 วิธีที่แตกต่างกันในการเรียกใช้งานใน TPL เพราะพวกเขาทำงานเหมือนกันทั้งหมด: Task.Start(), และTask.Run()Task.Factory.StartNew()

บอกฉันกำลังTask.Start(), Task.Run()และTask.Factory.StartNew()ทั้งหมดมาใช้เพื่อวัตถุประสงค์เดียวกันหรือพวกเขาไม่ได้มีความสำคัญแตกต่างกันอย่างไร

เมื่อหนึ่งควรใช้Task.Start()เมื่อควรจะใช้อย่างใดอย่างหนึ่งTask.Run()และเมื่อควรจะใช้อย่างใดอย่างหนึ่งTask.Factory.StartNew()?

โปรดช่วยฉันเข้าใจการใช้งานจริงของพวกเขาตามสถานการณ์โดยมีรายละเอียดที่ดีพร้อมตัวอย่างขอบคุณ



นี่คือตัวอย่างของการที่Task.Startมีประโยชน์จริง
noseratio

คำตอบ:


171

Task.Runเป็นการจดชวเลขสำหรับTask.Factory.StartNewอาร์กิวเมนต์ที่ปลอดภัยเฉพาะ:

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

มันถูกเพิ่มเข้ามาในสุทธิ 4.5 เพื่อช่วยให้มีการใช้งานบ่อยมากขึ้นและการทำงานถ่ายไปasyncThreadPool

Task.Factory.StartNew(เพิ่มด้วย TPL ใน. Net 4.0) นั้นแข็งแกร่งกว่ามาก คุณควรใช้มันถ้าTask.Runไม่เพียงพอตัวอย่างเช่นเมื่อคุณต้องการที่จะใช้TaskCreationOptions.LongRunning(แม้ว่ามันจะไม่จำเป็นเมื่อผู้ร่วมประชุมเป็น async เพิ่มเติมเกี่ยวกับที่บนบล็อกของฉัน:. LongRunning คือไร้ประโยชน์สำหรับ Task.Run ด้วย async-รอคอย ) เพิ่มเติมเกี่ยวกับTask.Factory.StartNewในTask.Run เทียบกับ Task.Fartory.StartNew

อย่าสร้างTaskและโทรStart()เว้นแต่คุณจะพบเหตุผลที่ดีอย่างยิ่ง มันควรจะใช้ถ้าคุณมีบางส่วนที่จำเป็นต้องสร้างงาน แต่ไม่ได้กำหนดเวลาพวกเขาและส่วนอื่นที่กำหนดโดยไม่ต้องสร้าง นั่นแทบไม่เคยเป็นทางออกที่เหมาะสมและอาจเป็นอันตรายได้ เพิ่มเติมใน"Task.Factory.StartNew" vs "new Task (... ). Start"

สรุปได้ว่าส่วนใหญ่ใช้Task.Runการใช้งานถ้าคุณต้องและไม่เคยใช้Task.Factory.StartNewStart


5
u กล่าวว่า "ไม่เคยสร้างงานและโทร Start ()" นำฉันไปสู่บทความที่ดีซึ่งจะแสดงให้เห็นว่าอาจเกิดจาก Task.Start () ฉันต้องการรายละเอียดเพราะคุณกำลังพูดเพื่อหลีกเลี่ยง ขอบคุณสำหรับการตอบ.
หมู

ru พูดคุยเกี่ยวกับลิงค์นี้blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx ??
หมู

1
@Mou Task.Startมีสถานที่สำหรับสืบทอดประเภทส่วนใหญ่
Yuval Itzchakov

1
@Mou มันไม่มีประสิทธิภาพเนื่องจากมันต้องการการซิงโครไนซ์เพื่อให้แน่ใจว่ามันถูกเรียกเพียงครั้งเดียว ตัวเลือกอื่นทำไม่ได้
i3arnon

2
@Mou คุณอาจจะอ่านโพสต์ที่อธิบายถึงปัญหานี้blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

คำตอบสั้น ๆ :

หากคุณไม่ได้ใช้งานของเด็กซ้อนและต้องการให้งานของคุณถูกดำเนินการบนThread PoolTask.Runเสมอการใช้ดีกว่า

คำตอบยาว:

Task.Runและ Task.Factory.StartNewทั้งสองให้การสนับสนุนสำหรับการสร้างและการจัดตารางวัตถุงานดังนั้นเราจึงไม่จำเป็นต้องสร้างTaskและโทรStart()

Task.Run(action);

เทียบเท่ากับ:

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

และ

Task.Factory.StartNew(action);

เทียบเท่ากับ:

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

Task.Runใช้TaskCreationOptions.DenyChildAttachซึ่งหมายความว่างานของเด็กไม่สามารถแนบกับผู้ปกครองและใช้TaskScheduler.Defaultซึ่งหมายความว่างานที่ทำงานในสระว่ายน้ำ Thread จะใช้ในการทำงาน

Task.Factory.StartNewใช้TaskScheduler.Currentซึ่งหมายถึงกำหนดการของเธรดปัจจุบันอาจเป็นTaskScheduler.Defaultแต่ไม่เสมอไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.