使用 C# 多线程循环遍历集合
Multi-threaded loop through collection with C#
我看过很多关于如何执行此操作的示例(阅读了本网站上的很多主题),但我很难在不 锁定 UI thread 并且允许我控制一次执行的线程数。
我有这个方法,它循环遍历集合并调用异步方法来处理项目,但它锁定了 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' 方法调用另一个方法,该方法通过互联网进行一些 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);
}
}
您的 ProcessItem
方法被标记为 async
,它 returns 一个 Task
,这表明它 应该 是异步的,但实际上不是异步的。它将完全同步执行。 async
仅允许在方法中使用 await
,并没有实际使方法异步。您当前收到一个编译器警告,通知您这一事实。
如果您使用的 API 公开了一个实际的异步方法来上传您尝试上传的文件,您应该使用它而不是同步版本。如果没有,那么虽然它是不可取的,但您需要使用 Task.Run
(或等效方法)来异步地 运行 线程池线程中的同步方法。
我看过很多关于如何执行此操作的示例(阅读了本网站上的很多主题),但我很难在不 锁定 UI thread 并且允许我控制一次执行的线程数。
我有这个方法,它循环遍历集合并调用异步方法来处理项目,但它锁定了 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' 方法调用另一个方法,该方法通过互联网进行一些 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);
}
}
您的 ProcessItem
方法被标记为 async
,它 returns 一个 Task
,这表明它 应该 是异步的,但实际上不是异步的。它将完全同步执行。 async
仅允许在方法中使用 await
,并没有实际使方法异步。您当前收到一个编译器警告,通知您这一事实。
如果您使用的 API 公开了一个实际的异步方法来上传您尝试上传的文件,您应该使用它而不是同步版本。如果没有,那么虽然它是不可取的,但您需要使用 Task.Run
(或等效方法)来异步地 运行 线程池线程中的同步方法。