Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# 用C语言实现多线程循环遍历集合#_C#_Multithreading_Threadpool_Asyncfileupload - Fatal编程技术网

C# 用C语言实现多线程循环遍历集合#

C# 用C语言实现多线程循环遍历集合#,c#,multithreading,threadpool,asyncfileupload,C#,Multithreading,Threadpool,Asyncfileupload,我已经看到了很多关于如何做到这一点的例子(在这个网站上阅读了很多线程),但是我很难在不锁定UI线程的情况下获得一些有效的东西,并且允许我控制每次执行的线程数 我有一个方法,它在集合中循环并调用一个异步方法来处理项,但它会锁定UI async Task ProcessItems() { using (var semaphore = new SemaphoreSlim(5)) { var tasks = MyCollection

我已经看到了很多关于如何做到这一点的例子(在这个网站上阅读了很多线程),但是我很难在不锁定UI线程的情况下获得一些有效的东西,并且允许我控制每次执行的线程数

我有一个方法,它在集合中循环并调用一个异步方法来处理项,但它会锁定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);
        }
    }
“ProcessItem”方法调用另一个方法,该方法通过internet进行一些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";
    }

您的
ProcessItem
方法被标记为
async
,它返回一个
任务
,这表明它应该是异步的,但实际上不是异步的。它将完全同步执行
async
只允许在方法中使用
Wait
,而不允许实际使方法异步。您当前收到一条编译器警告,通知您这一事实


如果您使用的API公开了一个实际的异步方法来上载您试图上载的文件,那么您应该使用该方法而不是同步版本。如果没有,那么尽管这是不可取的,但您需要使用
任务。Run
(或等效程序)在线程池线程中异步运行同步方法。

您的
ProcessItem
方法标记为
async
,并返回一个
任务,这表明它应该是异步的,但实际上它不是异步的。它将完全同步执行
async
只允许在方法中使用
Wait
,而不允许实际使方法异步。您当前收到一条编译器警告,通知您这一事实


如果您使用的API公开了一个实际的异步方法来上载您试图上载的文件,那么您应该使用该方法而不是同步版本。如果没有,那么尽管这是不可取的,但您需要使用
任务。运行
(或等效程序)以异步方式在线程池线程中运行同步方法。

如果ProcessItems方法锁定UI,则说明ProcessItem方法中存在错误。我怀疑它可以同步工作,发布
ProcessItem
的代码。您可以将创建的线程保存到集合/数组/列表中,然后检查哪个线程仍然有效。为什么需要对线程数进行细粒度控制?在几乎所有情况下,最好允许线程池或另一个框架方法处理分配线程;它几乎肯定会比你做得更有效。你提供的代码完全是异步的。如果它阻塞了UI线程,则是由于调用堆栈上该方法上方或下方的代码未显示。@Fubak:阅读编译器在
ProcessItem
方法上给您的警告。如果ProcessItems方法锁定UI,则说明您在ProcessItem方法中做了错误的事情。我怀疑它可以同步工作,发布
ProcessItem
的代码。您可以将创建的线程保存到集合/数组/列表中,然后检查哪个线程仍然有效。为什么需要对线程数进行细粒度控制?在几乎所有情况下,最好允许线程池或另一个框架方法处理分配线程;它几乎肯定会比你做得更有效。你提供的代码完全是异步的。如果它阻塞了UI线程,那是因为没有显示代码,在调用堆栈上该方法的上方或下方。@Fubak:阅读编译器在
ProcessItem
方法上给您的警告。您可以添加一些示例,说明使用Task.Run时我的代码会是什么样子吗?@Fubak将要在
任务的线程池中运行的方法包装起来。运行
调用并
等待它。@Fubak或删除它。@Fubak
async
并返回任务。作为警告,您可以添加一些示例,说明使用Task.Run时我的代码会是什么样子?@Fubak您可以将要在
任务的线程池中运行的方法包装起来。运行
调用并等待它。@Fubak或删除
异步
,然后返回任务。作为警告
    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);
        }
    }