访问 Task.ContinueWith 中的值 [英] Accessing values in Task.ContinueWith

查看:35
本文介绍了访问 Task.ContinueWith 中的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码开始一项任务:

I am starting a task with the following code:

var token = tokenSource.Token;
var taskWithToken = new Task(() =>
        new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute(), 
        token);

在我继续的过程中,我需要知道 ... 中列出的 batchRunId 和可能的一些其他变量,但是,这并不可能?

In my continue with, I need to know the batchRunId and possibly some other variables listed in the ..., however, it doesn't apepar that this is possible???

taskWithToken.ContinueWith(task =>
        {
            if (!task.IsCanceled)
                return;

            //TODO: make sure no more subsequent runs happen

            //TODO: sync with source data
        }
    );

有什么我遗漏的吗?我怎样才能确保 .ContinueWith 在访问它需要的值的情况下执行?

Is there something I am missing? How can I make sure the .ContinueWith executes with access to the values it needs?

推荐答案

首先,我什至不确定您是否需要继续处理您的情况.您的代码可以简化为:

First, I'm not even sure if you need continuation in your case. Your code could be simplified into something like:

var taskWithToken = new Task(() =>
    {
        new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute();

        // code from the continuation here
    },
    token);

但是如果您确实想使用 ContinueWith() 并且您因为 ReSharper 警告而担心使用它,那么您不必这样做.大多数情况下,这样的代码完全没问题,您可以忽略警告.

But if you do want to use ContinueWith() and you're worried about using it because of the ReSharper warning, then you don't have to. Most of the time, code like this is perfectly fine and you can ignore the warning.

更长的版本:当您编写一个引用封闭范围内某些内容的 lambda 时(所谓的 闭包),编译器必须为此生成代码.它究竟是如何做到的,这是一个实现细节,但当前的编译器为单个方法中的所有闭包生成一个闭包类.

Longer version: when you write a lambda that references something from the enclosing scope (so called closure), the compiler has to generate code for that. How exactly does it do that is an implementation detail, but the current compiler generates a single closure class for all closures inside a single method.

在您的情况下,这意味着编译器生成一个包含本地this(因为_unitOfWork)、requestbatchRunId(可能还有其他您没有显示的).这个闭包对象在 new Task lambda 和 ContinueWith() lambda 之间共享,即使第二个 lambda 不使用 request 或 <代码>这个.只要从某处引用第二个 lambda,这些对象就不能被垃圾回收,即使它们不能从中访问.

What this means in your case is that the compiler generates a class that contains the locals this (because of _unitOfWork), request and batchRunId (and maybe others that you didn't show). This closure object is shared between the new Task lambda and the ContinueWith() lambda, even though the second lambda doesn't use request or this. And as long as the second lambda is referenced from somewhere, those objects can't be garbage collected, even though they can't be accessed from it.

因此,这种情况会导致内存泄漏,我相信这就是 ReSharper 警告您的原因.但在几乎所有情况下,这种内存泄漏要么不存在(因为第二个 lambda 的引用时间不长于第一个),要么非常小.因此,大多数情况下,您可以放心地忽略该警告.但是,如果您遇到神秘的内存泄漏,您应该调查您使用 lambda 的方式,尤其是您收到此警告的地方.

So, this situation can lead to a memory leak, which I believe is why ReSharper is warning you about it. But in almost all cases, this memory leak either doesn't exist (because the second lambda isn't referenced longer than the first one) or it's very small. So, most of the time, you can safely ignore that warning. But if you get mysterious memory leaks, you should investigate the way you're using lambdas and especially places where you get this warning.

这篇关于访问 Task.ContinueWith 中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆