【问题标题】:Why are new instances of a list being created when adding Tasks?为什么添加任务时会创建列表的新实例?
【发布时间】:2019-04-23 21:39:59
【问题描述】:

我有一个 asp.net 应用程序,用户可以在其中按下一个按钮来启动一个长时间运行的操作,并且可以多次这样做。每次他们这样做时,我都想将创建的任务添加到列表中,以便稍后当他们想要进入下一页时,页面会等待列表中的所有任务完成后再重定向。

我有以下结构:

private List<Task> tasks = new List<Task>();
private SemaphoreSlim mutex = new SemaphoreSlim(1, 1);

// Simulate some work
private async Task MyWork()
{
    int t = 0;
    while (t < 5)
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        t ++;
    }
}

// Called in the button's eventhandler
public void DoWork()
{
    mutex.Wait();
    this.tasks.Add(Task.Run(() => MyWork());
    mutex.Release();
}

在调试时我发现每次 DoWork 访问任务列表时,将任务添加到列表中时列表为空,似乎每次都创建一个单独的列表实例。另外,当我稍后以另一种方法访问该列表时,那里的列表是空的。

为什么会发生这种情况,而不是将每个任务添加到同一个列表实例中?

【问题讨论】:

  • 你能在你实例化包含 DoWork 方法的类的地方添加代码吗?
  • 所以在用户按下按钮时,服务器端请求会发送到您将任务添加到列表的位置?每个服务器端请求不会创建一个新的上下文,从而创建一个新的列表吗?这可能是您的列表开始时长度为 0 的原因。尝试使用静态/单例实例,看看它是否有效
  • @sayahimad 类的构造函数在这里不与任何东西交互。
  • @pmain8 你会多次实例化你的类吗?
  • @sayahimad 理论上可能是这样,但在我的测试中我只做了一次。

标签: c# asp.net async-await


【解决方案1】:

当 ASP.NET 收到新请求时,它会为您的页面创建一个新实例。这就是为什么您总是看到一个空列表。

应该做的是让您的按钮处理程序创建一个请求 ID(例如 Guid),将该请求插入到可靠队列中,然后使用该请求 ID 更新会话状态。因此,您有一个请求 ID(字符串)列表,而不是任务列表。然后从该队列中读取一个单独的工作进程并执行实际工作。最后,“等待”页面应该轮询直到请求全部完成。

【讨论】:

    猜你喜欢
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    相关资源
    最近更新 更多