【问题标题】:How to check task status in c#如何在c#中检查任务状态
【发布时间】:2017-03-22 11:35:51
【问题描述】:

我想知道如何在 c# 中检查异步任务的状态。 我有一个保存方法来保存用户,我想在保存后运行一个后台任务来更新他们。

我在框架 4.0 中,这是我开始任务的代码

 System.Threading.Tasks.Task task = null;
 task = System.Threading.Tasks.Task.Factory.StartNew(() =>
       {                   
             beginTask();
       });

我的问题是任务需要一些时间才能结束(接近 7 分钟),所以如果有人进行了多次用户保存,任务会运行多次,所以我想在运行任务之前检查函数 beginTask()已经在运行以避免有大量后台任务正在运行。

谢谢

【问题讨论】:

  • 任务结束时会发生什么?您的任务对象是否存储在某处以在运行前对其进行检查?
  • 是的,BeginTask() 会一一保存用户更新一个字段。所以这需要很长时间,因为我需要等待 5 秒来更新用户,因为我调用了一个 API,我每 5 秒不能请求超过一次。这就是为什么我想检查 beginTask() 是否已经在运行以避免在前一个调用运行时发生两次或更多保存时执行它
  • 在命令执行时禁用 UI 按钮怎么样?

标签: c# multithreading task


【解决方案1】:

也许尝试这样做- 初始化你的任务对象:

Task task = new Task(begintask);

并添加新方法来运行它,例如:

public void StartTask(Task t)
{
    if (t.Status == TaskStatus.Running)
        return;
    else
        t.Start();
}

当然,您可以根据任务的状态添加更多条件。

【讨论】:

  • 不错的代码,但问题是每次我保存用户时,它都会创建一个状态为“已创建”的新任务,所以我无法测试之前的 BeginTask() 是否仍在运行
  • 你真的需要创建新的 tsks 吗?也许只是尝试将任务作为私有字段添加到您的类中,然后为其分配适当的方法并启动它(我的代码中的 StartTask 方法)。
  • 不,我不需要,但是如何在不使用“new Task(beginTask());”的情况下分配我的类属性?我有一个空引用错误,因为我的属性从未实例化
  • 我添加了新答案。请检查一下。
【解决方案2】:

我想我找到了更好的解决方案。检查它是否适合您。

public class TaskDemo
{
    private static AutoResetEvent autoReset = new AutoResetEvent(true);

    Action beginTask = () =>
    {
        Console.WriteLine("Method start");
        Thread.Sleep(2000);
    };

    public void RunTask()
    {
        Task myTask = Task.Run(() =>
            {
                autoReset.WaitOne();
                beginTask();
            }).ContinueWith(t => autoReset.Set());
    }
}

简单的控制台应用测试:

static void Main(string[] args)
    {
        TaskDemo td = new TaskDemo();
        // Simulation multiple requests 
        Thread.Sleep(1000);
        td.RunTask();
        Thread.Sleep(1000);
        td.RunTask();
        Thread.Sleep(1000);
        td.RunTask();
        Thread.Sleep(1000);
        td.RunTask();
        Thread.Sleep(1000);
        td.RunTask();
        Thread.Sleep(1000);
        td.RunTask();
    }

线索是使用AutoResetEvent来表示任务状态和

Task myTask = Task.Run(() =>
            {
                autoReset.WaitOne();
                beginTask();
            }).ContinueWith(t => autoReset.Set());

在运行期间和完成后更改其状态 (ContinueWith(t => autoReset.Set())。

【讨论】:

  • StartNew 应该避免使用,并且不应该使用类字段来完成,它甚至没有标记为volatile,这也很危险。您需要在这里使用自动重置事件
  • 为什么? Task.Run 会更好吗?
  • @VMAtm 我已根据您的评论更改了我的答案。现在好点了吗?
  • @daniell89 我希望是的 :)
【解决方案3】:

每个Task 对象都有一个Task.Status 类型的TaskStatus 属性,如果您已经拥有任务对象,则可以查询该属性。它会告诉您任务是否正在运行、已完成、已取消等。

如果您想检查是否有任何任务正在运行可能更困难的特定功能块。一个可能的建议是保持一个 Task 变量可以全局访问,并且任何时候他们尝试运行该代码都会执行的功能:

检查全局以查看是否有一个正在运行。

如果 创建一个新任务来运行它并将其分配给全局变量

否则如果它已经在运行,则执行您想做的任何处理(也许等待它完成?)

听起来你 a) 有点误解了任务 b) 需要看看你的解决方案设计。

任务是表示要完成的工作的对象。任务不是 BeginTask 方法本身。 BeginTask 方法或多或少只是一组要执行的指令。它没有任何状态。实现这些指令的单个任务确实具有可以查询的状态。

如果您想让每个用户只能运行一个任务,您只需要在某个地方全局存储每个用户的任务集合(例如以用户为键的字典)。

理想情况下,这将被创建并存储在某种包含这部分应用程序功能的管理类中,或者如果它是一个外部程序,则存储在外部程序中。

要参考您的评论“我需要避免在每次保存我的用户时创建新任务”,为此您将不得不调整该特定代码以检查任何运行的存储状态任务。因此,在我上面的想法中,您将更改该功能以检查您保存在已开始任务字典中的用户是否存在任务,如果存在,请检查它的状态。

如果您不确定,请继续在 cmets 中提问。也许如果你提供更多关于这个系统的信息,我会更好地提供帮助。

希望对您有所帮助。

【讨论】:

  • 是的,但我在上课,每次保存用户时我都需要避免创建新任务。 BeginTask() 只有在它不处于“运行”状态时才必须执行。每次我保存我的用户时,它都会创建一个状态为“已创建”的新任务,因此我无法检查 beginTask() 是否由于以前的用户保存而正在运行
  • @VincentDucroquet 我已经通过回复您的评论更新了我的答案,它本身的评论太长了。如果我误解了什么,请继续质疑我。
【解决方案4】:

您可以使用属性Task.IsCompletedTask.Status

顺便试着调查一下这个方法Task.ContinueWith 我认为使用Task.ContinueWith 是多任务解决方案的更好方法。

请参阅下面的示例,该示例解释了我使用 Task.ContinueWith 的建议:

System.Threading.Tasks.Task task = null;
if (task==null)
{
    task = Task.Factory.StartNew(() =>
    {
        beginTask();
        
    });
    return;
}

if (task.Status == TaskStatus.Running)
{
    task.ContinueWith((x) =>
    {
        beginTask();

    });
}
else
{
    task = Task.Factory.StartNew(() =>
    {
        beginTask();

    });

}

此实现可以解决潜在问题的范围,例如:

  • 如何保留以前的任务
  • 系统应该何时启动以前的任务

【讨论】:

  • 不错的代码,但我在一个类(用户类)中,每次我保存用户时它都会创建一个新任务,这是我的问题。如果 beginTask() 当前正在运行,则需要一种检查线程的方法。如果我可以检查,我可以阻止另一个 beginTask() 执行
  • 你的意思是:在 beginTask 方法中检查最后一个任务状态的方法,对吧?
猜你喜欢
  • 2012-02-20
  • 2022-10-15
  • 2016-07-20
  • 2020-01-27
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
相关资源
最近更新 更多