任务似乎自动启动

3

我正在移植一个程序,它的加载时间非常长,即使我进行了移植,也没有得到改善,因为缓慢是由于访问数据库服务器(而不是不良代码)引起的。我使用 Tasks 库将加载移动到单独的线程中,现在 UI 在加载时不会冻结,但这让我对某些事情感到好奇:

Task.Factory 对象有一个方法 StartNew,它应该创建一个新任务,启动它并返回对它的引用。这很有道理,但似乎 Task 构造函数也做同样的事情。

当我执行以下操作时:

Task catsFromDB = new Task(() => AddCategoriesFromDB(cts.Token), cts.Token);
catsFromDB.Start();

我遇到了一个错误InvalidOperationException,但我真的不明白。它似乎认为我已经启动了它,但事实并非如此。

[编辑]

错误信息是:"InvalidOperationException,不能在已完成任务上调用Start"

[编辑]

错误是由我包含的一些取消代码引起的。在尝试重新运行之前,我需要重置取消。


你确定它真的启动了吗? - Edwin de Koning
@Rewinder:是的,因为它“运行得很好”。 - Chris Pfohl
抱歉,周末之后我才回来。我错了,它不起作用。 - Chris Pfohl
请提供完整的堆栈跟踪。 - Drew Marsh
3个回答

6

现在我感到很蠢,但从我的“新手”错误中学习教训将是有益的:

我需要可取消并可重新运行的操作,因此在执行实际加载之前,我实现了一个“CancelLoad”操作。结果发现,在取消和等待后,我忘记创建新的Token。


1
我犯了同样的错误。我想要在用户点击按钮两次时重复一个过程(SignalR)。因此,在我的初始化过程中,我首先对令牌源引用调用了 cancel。感谢你提醒我,你帮我省去了很多抓狂的时间。 - Ody

1

我无法复现那种行为。下面的代码只有在调用Start时才会启动任务。

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

class Test
{
    static void Main()
    {
        var cts = new CancellationTokenSource();
        Console.WriteLine("Creating task...");
        Task task = new Task(() => Console.WriteLine("Task executing"),
                             cts.Token);
        Console.WriteLine("Sleeping...");
        Thread.Sleep(1000);
        Console.WriteLine("Starting task...");
        task.Start();
        Thread.Sleep(1000);
    }
}

我的猜测是你可能在创建多个任务并且有些任务被启动了两次,而有些则没有被启动。如果你能提供一个类似的简短但完整的程序来演示这个问题,我们应该能够提供更多帮助。


嗯...这是个好想法,但快速的“在整个解决方案中查找”显示new Task只出现了一次。我会看看能否准备另一个示例。 - Chris Pfohl

0

我的猜测是与UI相关的:我认为你可能在AddCategoriesFromDB(cts.Token)中有更新UI的代码。然而,由于你现在处于不同的线程上,你对UI的更新将会抛出错误。这是情况吗?


这是正确的。它确实更新了用户界面,但我使用了“BeginInvoke”。 - Chris Pfohl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接