2015-10-04 65 views
2

我有以下方法:将数据传入任务延续

private void GetHistoricalRawDataFromTextFiles(MessageHeader header, HistoricalRawDataFromTextFileSubscriptionDto dto) 
{ 
    var computeInstance = GetComputeInstance(dto.SubscriberId, dto.ComputeInstanceId); 
    var task = computeInstance.GetHistoricalRawDataFromTextFiles(dto, progress => SendProgress(header.Sender, progress)); 

    task.ContinueWith(myTask => 
    { 
     dto.TimeSeries = myTask.Result; 
     Messenger.SendTo(SubscriberId, header.Sender, MessageType.Reply, MessageTopic.HistoricalRawDataFromTextFiles, dto); 
    }); 
} 

方法computeInstance.GetHistoricalRawDataFromTextFiles返回Task<List<string>>,我的问题是

  • 这是否是通过headerdto到拉姆达的正确方法表达和任务延续。在外部方法被调用时,在lambda表达式和任务延续内捕获headerdto实例值是很重要的。在上次调用的任务完成之前,可能会再次调用相同的方法。

回答

1

,所述报头和DTO实例值被捕获 lambda表达式和任务继续在 外方法被调用的时间内是很重要的。

当使用lambda表达式,得到什么关闭了是可变,而不是该变量的值

只要headerdto不是您在进行方法调用之前每次修改的全局变量,那么您应该没问题。如果他们全局变量,那么你需要找到一种方法来为它们中的每一个创建本地副本。如果它们是引用类型,则需要克隆它们,如果它们是值类型,则需要将它们复制到lambda内的局部变量。

+0

它们不是全局变量,因为它们可以全局访问,但是,每个外部消息调用都会改变'header'和'dto'。那么,唯一的方法就是克隆它们,然后将克隆传递给lambda和任务? –

+0

不,如果它们不是全局可修改的,并且每次都传递一个新实例,那么代码没问题。 –

+0

谢谢,这使得它更清晰,所以,这只是归结为我传入了对'header'和'dto'值的新引用,是正确的吗? –

1

我认为你的问题归结为:“我的方法线程安全吗?”

我不认为它与你捕获的变量有关。

你的方法不似乎访问共享/全局源(静态/全局变量或字段)。(否则你需要同步)

即使这种方法是由多个线程调用同时它仍然是线程安全的,每次调用GetHistoricalRawDataFromTextFiles将处理一个单独的“领域” - 这是因为每个线程都有自己的堆栈。

所以,无论你是否使用捕获变量(指同一内存位置) - 你仍然可以获得独特dtoheader每次迭代的境界。

因为每次调用(即使是线程化的),我都没有在这里看到任何相同的共享内存位置问题 - 获取它自己的空间。

再次。这假设你没有使用任何全局状态。

+0

你准确定义**全局变量**是什么?甚至可以在同一个线程中短时间连续地调用外部方法'private void GetHistoricalRawDataFromTextFiles(MessageHeader header,HistoricalRawDataFromTextFileSubscriptionDto dto)'(每个方法都有不同的'header'和'dto'实例),并且这个想法是旋转任务并且运行他们的延续,以“捕获”当时传入方法的'header'和'dto'。我想我担心第二个方法调用会影响第一个方法调用期间启动的任务及其延续。 –

+0

@MattWolf通过全局变量,我的意思是一个可以从函数外部访问的变量。 [它不一定是静态的](https://dotnetfiddle.net/uPdsKX) –