将Task作为方法参数传递是否安全?

时间:2015-09-08 10:25:10

标签: c# multithreading asynchronous

请考虑以下代码:

public class Program {
    static void Main(string[] args) {
        Generate();
    }

    static void Generate() {
        Task t = null;
        t = Task.Run(() => {
            MyClass myClass = new MyClass();
            myClass.ContinueTask(t);
        });
        Console.ReadLine();
    }
}
public class MyClass {

    public void ContinueTask(Task t) {
        t.ContinueWith(x => {
            Console.WriteLine("Continue here...");
        });
    }
}

将t作为参数传递是否安全,或者直接在MyClass中启动新任务是否更好?

2 个答案:

答案 0 :(得分:1)

我已将代码缩减到此示例:

public Task<int> Parse()
{
    Task<int> t = null;
    t = Task.Run(() => this.Read(t));
    return t;
}

public Task<int> Read(Task<int> t)
{
    return t.ContinueWith(v => 42);
}

我认为它具有相同的基础结构。

这导致死锁。我怀疑你的代码也是如此。所以我觉得它不安全。

答案 1 :(得分:1)

这是不安全的,因为t可能不会在使用它时指定。事实上,这是一场数据竞赛。

即使你修复了这将是糟糕的架构。为什么ContinueTask需要知道它正在继续某些事情。这不是一个应该位于此处的问题。 ContinueTask假设其前提已经完成,应该执行它的工作。

很难说出你想要完成的事情。对代码进行排序有什么问题:?

static async Task Generate() {
    var t = Task.Run(() => {
     //... other code ...
    });

    MyClass myClass = new MyClass();
    await t;
    myClass.ContinueTask();

    Console.ReadLine();
}

await非常适合测序任务。

  

重用Task对象

你是什么意思?任务无法重复使用。它不能运行两次。你ContinueWith做的所有事情都在逻辑上等待先行者然后运行lambda。在这里,任务基本上是一个事件。

ContinueWith不会修改正在调用的任务。它创造了一项新任务。