使用C#进行多线程循环收集

时间:2015-02-26 14:43:43

标签: c# multithreading threadpool asyncfileupload

我已经看到很多关于如何执行此操作的示例(通过此站点上的大量线程阅读),但是我很难在没有锁定UI线程的情况下获得有用的东西< / strong> AND允许我控制一次执行的线程数

我有这个方法,它循环遍历集合并调用异步方法来处理项目,但它会锁定UI ......

    async Task ProcessItems()
    {
        using (var semaphore = new SemaphoreSlim(5))
        {
            var tasks = MyCollection.Select(async (MyItem) =>
            {
                await semaphore.WaitAsync();
                try
                {
                    await ProcessItem(MyItem);
                }
                finally
                {
                    semaphore.Release();
                }
            }).ToArray();

            await Task.WhenAll(tasks);
        }
    }

&#39; ProcessItem&#39;方法调用另一个方法,它通过互联网进行一些API调用来上传一些文件。

这一直有效,但我无法控制一次执行多少个线程......

    foreach (MyItemClass MyItem in MyCollection)
    {
        MyItemClass tmp = logItem;
        Thread thread = new Thread(() => ProcessItem(tmp));
        thread.Start();
    }

编辑:这是ProcessItem方法......

    public async Task<string> ProcessItem(MyItemClass MyItem)
    {
        MyItem.Status = "Transferring";

        HelperClass.UploadFileOrFolder(
            siteUrl,
            MyItem.DocumentLibrary,
            MyItem.RootFolder,
            srcRootPath,
            MyItem.SourcePath);

        MyItem.Status = "Transferred";

        return "Transferred";
    }

这是UploadFileorFolder方法,它使用SharePoint.Client.File.SaveBinaryDirect方法将文件上传到SharePoint ...

    public static void UploadFileOrFolder(string siteUrl, string libraryName, string rootFolder, string path, string file)
    {
        ClientContext ctx = GetSPContext(siteUrl);

        using (fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true))
        {
            Microsoft.SharePoint.Client.File.SaveBinaryDirect(ctx, targetFileUrl, fs, true);
        }
    }

1 个答案:

答案 0 :(得分:4)

您的ProcessItem方法被标记为async,并返回Task,表示假设是异步的,但事实并非如此异步。它将完全同步执行。 async仅允许在方法中使用await,并且实际上不会使方法异步。您目前正在收到编译器警告,告知您这一事实。

如果您使用的API公开了一个实际上异步的方法来上传您尝试上传的文件,那么您应该使用它而不是同步版本。如果没有,那么虽然它是不合需要的,但您需要使用Task.Run(或等效的)来异步运行线程池线程中的同步方法。