c#-如何在主线程上执行代码,直到任务完成

时间:2018-08-30 03:06:00

标签: c# task-parallel-library

我想更好地了解TPL。例如,在任务完成之前,我将如何在屏幕上写一些东西。我无法调用“ await”,因为我希望通知主线程,而不是主动调用“ await”,并且我不想在任务完成之前停止执行。

一些示例代码:

var task = Task.Run(()=>
{
   Task.Delay(10000);
});


while(true)
{
    Console.WriteLine("Running...");
    //I want to exit the loop the second 'task' finishes
    //and print 'finished'
}

4 个答案:

答案 0 :(得分:0)

尝试执行以下操作:

var task = Task.Run(() =>
{
    Task.Delay(10000).Wait();
});


bool terminate = false;
while (!task.GetAwaiter().IsCompleted && !terminate)
{
    // do something 

    if (task.GetAwaiter().IsCompleted) break;
    // do something heavy

    if (task.GetAwaiter().IsCompleted) break;
    // do another heavy operation

    for (int i = 0; i < 10000; i++)
    {
        // it took too long!
        if (i == 1000)
        {
            terminate = true;
            break;
        }
    }

}

答案 1 :(得分:0)

ContinueWith函数是任务上可用的方法,允许在任务完成执行后执行代码。简而言之,它允许继续。

这里要注意的是ContinueWith还返回一个Task。这意味着您可以附加ContinueWith这个方法返回的一个任务。

   Task<string> t = Task.Run(() => LongRunningOperation("Continuewith", 500));  
   t.ContinueWith((t1) =>  
   {  
      Console.WriteLine("Running..."); 
   });  

答案 2 :(得分:0)

您可以通过以下两种方法实现此目标:

首先,您可以在Order中使用Lambda表达式来调用您的操作,但请查看代码:

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Console.WriteLine("Application thread ID: {0}",
                        Thread.CurrentThread.ManagedThreadId);
      var t = Task.Run(() => {  Console.WriteLine("Task thread ID: {0}",
                                   Thread.CurrentThread.ManagedThreadId);
                             } );
      t.Wait();
   }
}
// The example displays the following output:
//       Application thread ID: 1
//  

注意t.Wait()

  

Wait方法的调用可确保任务完成并   在应用程序结束之前显示其输出。不然是   可能在任务完成之前完成Main方法。

因此,我们了解必须调用Wait()方法,以确保任务完成并显示其输出

您还可以使用第二种方法:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var list = new ConcurrentBag<string>();
      string[] dirNames = { ".", ".." };
      List<Task> tasks = new List<Task>();
      foreach (var dirName in dirNames) {
         Task t = Task.Run( () => { foreach(var path in Directory.GetFiles(dirName)) 
                                       list.Add(path); }  );
         tasks.Add(t);
      }
      Task.WaitAll(tasks.ToArray());
      foreach (Task t in tasks)
         Console.WriteLine("Task {0} Status: {1}", t.Id, t.Status);

      Console.WriteLine("Number of files read: {0}", list.Count);
   }
}

有关更多参考,请参见Task.Run Method


有关您的疑问的重点

摘自Asynchronous programming with async and await (C#)

  

异步方法通常包含一个或多个await的出现   运算符,但是缺少await表达式不会导致   编译器错误。如果异步方法未使用await运算符   标记一个悬浮点,该方法将作为同步方法执行   尽管使用了async修饰符。编译器发出警告   这样的方法。

这意味着您要么必须等待任务完成,而主线程要么必须等待这种方式。

答案 3 :(得分:0)

您可以通过创建单独的函数以在Task.Run中使用并通过引用传递参数来实现您的目标。功能应如下所示。

private void PerformTask(ref bool isComplete)
{
    System.Threading.Thread.Sleep(5000);
    isComplete = true;
}

Task.Run调用上述函数。您当前的功能应如下所示。

bool isComplete = false;
System.Threading.Tasks.Task.Run(() => PerformTask(ref isComplete));

while (!isComplete)
{
    Console.WriteLine("Running...");
    System.Threading.Thread.Sleep(1000);
}