Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何确保从taskList调用的方法不会';不能同时执行吗?_C#_Async Await_Task - Fatal编程技术网

C# 如何确保从taskList调用的方法不会';不能同时执行吗?

C# 如何确保从taskList调用的方法不会';不能同时执行吗?,c#,async-await,task,C#,Async Await,Task,我有一个方法,从cloudDrive下载一个memoryStream,然后将该memoryStream传递给taskList,taskList读取该文件: public async Task CreateFiles(List<MyDataClass> list) { var tasks = new List<Task>(); foreach (var item in list) { va

我有一个方法,从cloudDrive下载一个memoryStream,然后将该memoryStream传递给taskList,taskList读取该文件:

  public async Task CreateFiles(List<MyDataClass> list)
    {
        var tasks = new List<Task>();

        foreach (var item in list)
        {
            var memorySteam = await _cloudService.DownloadStreamFromCloudAsync(item);

            tasks.Add(Task.Run(() =>
            {
                using (memoryStream)
                {
                    ReadFile readFile = new ReadFile(memoryStream, new MyFileSerializer());
                    readFile.DoWork();
                }
                UpdateTreeViewRecursively();

            }));
        }
    }

    public void UpdateTreeViewRecursively()
    {
        //...
        //Here I do recursive operations on a treeView. This may take a while
    }
公共异步任务创建文件(列表)
{
var tasks=新列表();
foreach(列表中的变量项)
{
var memorySteam=wait_cloudService.DownloadStreamFromCloudAsync(项目);
tasks.Add(Task.Run)(()=>
{
使用(内存流)
{
ReadFile ReadFile=new ReadFile(memoryStream,new MyFileSerializer());
readFile.DoWork();
}
updateTreeViewRecursive();
}));
}
}
public void UpdateTreeViewRecursively()
{
//...
//这里我在树视图上执行递归操作。这可能需要一些时间
}
问题是,当一个任务完成并且文件被读取时,我调用一个方法来执行一些耗时的工作,并且有可能这个方法还没有完成,而下一个任务已经在再次调用它。我应该使用锁还是有其他解决方案

编辑: 我将尝试解释我为什么选择这样的架构:

1) 用户调用CreateFiles方法,开始从云下载:30个文件,大小从1mb到70mb不等。一次只能下载一个文件

2) 然后将每个下载的memoryStream传递到tasks.Add(..)。通过这样做,我希望实现几个文件可以同时读取,当一个文件被读取时,我递归调用UpdateTreeViewRecursive();此方法将treeViewItem标记为可供使用,并检查其父项的所有其他子项是否已下载并可供使用。通过这种方式,用户可以立即看到哪些文件可以使用,而不必等到处理了70mb的大文件后才开始使用该程序


3) 为了确保treeView中的标志设置正确,我需要确保UpdateTreeViewRecursive();方法在被前一个调用方执行时不会再调用一次

对任务使用锁或使用.Result.Run方法等待任务的结果。这样,主线程将等待任务完成

问题是,当一个任务完成并且文件被读取时,我调用一个方法来执行一些耗时的工作,并且有可能这个方法还没有完成,而下一个任务已经在再次调用它。我应该使用锁还是有其他解决方案

由于该方法正在修改UI线程,因此它应该在UI线程上运行。所以可能是这样的:

public async Task CreateFiles(List<MyDataClass> list)
{
  var tasks = list.Select(async item =>
  {
    using (var memorySteam = await _cloudService.DownloadStreamFromCloudAsync(item))
    {
      await Task.Run(() =>
      {
        ReadFile readFile = new ReadFile(memoryStream, new MyFileSerializer());
        readFile.DoWork();
      });
    }

    UpdateTreeViewRecursively();
  });
}
//使用IProgress的方法:
公共异步任务CreateFiles(列表)
{
var tasks=list.Select(异步项=>
{
使用(var memorySteam=await_cloudService.DownloadStreamFromCloudAsync(项目))
{
等待任务。运行(()=>
{
ReadFile ReadFile=new ReadFile(memoryStream,new MyFileSerializer());
readFile.DoWork();
});
}
var progress=新进度(更新=>updateMetreeViewItem(更新));
等待任务。运行(()=>UpdateTreeViewRecursively();
});
}
public void UpdateTreeViewRecursive(IProgress progress)
{
进度?报告(新的MyTreeViewItemUpdate(){…});
var data=somesLowCodethatNoTupDateUI();
进度?.Report(新的MyTreeViewItemUpdate(){…=数据…});
}

为什么不等到所有任务都读取完文件后再调用长时间运行方法1次呢?如果必须为每个任务调用长时间运行方法,那么是的,需要锁定以确保数据完整性。当只读取了部分文件时更新树状图有意义吗?是否在所有任务之后都不能更新它e文件已被读取?否则我想知道将任务放入调度程序队列是否会有所帮助?只是好奇,是否需要为列表中的每个项目递归调用UpdateTreeView?或者是否可以在所有任务完成后调用它一次?您能否不只是将所有任务添加到
任务
,而是执行
等待任务。whalll(tasks.ToArray())
一旦完成,就递归地调用
updatetreeview()
one?正在递归地调用
updatetreeview()
每个文件后都有一个要求?谢谢大家的回答。是的,这是在下载/创建每个文件后更新treeView的要求。谢谢你的回答。嗯,我没有想到UI上下文可以用作“锁”我想澄清一件愚蠢的事情——如果我从UI线程递归调用UpdateTreeViewMethod,比方说在一秒钟内调用400次,所有调用都会排队等待轮到它们一个接一个地执行?我做了一个小测试,是的,的确,所有调用都被执行了,但也许有一些事情我没有考虑过必须考虑at吗?@niks:UI线程上的所有代码都以独占方式一个接一个地运行。必须运行代码才能使其为真;如果方法
wait
s,则其他代码可以在等待时在UI线程上运行。
// Approach using Task.Run within UpdateTreeViewRecursively:
public async Task UpdateTreeViewRecursively()
{
  UpdateSomeTreeViewItem();
  var data = await Task.Run(() => SomeSlowCodeThatDoesNotUpdateUI());
  UpdateSomeOtherTreeViewItem(data);
}
// Approach using IProgress<T>:
public async Task CreateFiles(List<MyDataClass> list)
{
  var tasks = list.Select(async item =>
  {
    using (var memorySteam = await _cloudService.DownloadStreamFromCloudAsync(item))
    {
      await Task.Run(() =>
      {
        ReadFile readFile = new ReadFile(memoryStream, new MyFileSerializer());
        readFile.DoWork();
      });
    }

    var progress = new Progress<MyTreeViewItemUpdate>(update => UpdateSomeTreeViewItem(update));
    await Task.Run(() => UpdateTreeViewRecursively();
  });
}

public void UpdateTreeViewRecursively(IProgress<MyTreeViewItemUpdate> progress)
{
  progress?.Report(new MyTreeViewItemUpdate() { ... });
  var data = SomeSlowCodeThatDoesNotUpdateUI();
  progress?.Report(new MyTreeViewItemUpdate() { ... = data... });
}