C# 用C语言实现多线程循环遍历集合#
我已经看到了很多关于如何做到这一点的例子(在这个网站上阅读了很多线程),但是我很难在不锁定UI线程的情况下获得一些有效的东西,并且允许我控制每次执行的线程数 我有一个方法,它在集合中循环并调用一个异步方法来处理项,但它会锁定UIC# 用C语言实现多线程循环遍历集合#,c#,multithreading,threadpool,asyncfileupload,C#,Multithreading,Threadpool,Asyncfileupload,我已经看到了很多关于如何做到这一点的例子(在这个网站上阅读了很多线程),但是我很难在不锁定UI线程的情况下获得一些有效的东西,并且允许我控制每次执行的线程数 我有一个方法,它在集合中循环并调用一个异步方法来处理项,但它会锁定UI async Task ProcessItems() { using (var semaphore = new SemaphoreSlim(5)) { var tasks = MyCollection
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或删除它。@Fubakasync
并返回任务。作为警告,您可以添加一些示例,说明使用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);
}
}