【发布时间】:2015-02-26 14:43:42
【问题描述】:
我已经看到了很多关于如何做到这一点的示例(阅读了这个网站上的很多线程),但是我很难在不锁定 UI 线程的情况下获得一些可以工作的东西> 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);
}
}
“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";
}
这里是 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);
}
}
【问题讨论】:
-
如果 ProcessItems 方法锁定了 UI,那么你在 ProcessItem 方法中做错了。我怀疑它做同步工作,发布
ProcessItem的代码。 -
您可以将创建的线程保存到集合/数组/列表中,然后检查哪些线程还活着。
-
为什么需要对线程数进行细粒度控制?几乎在所有情况下,最好让线程池或其他框架方法处理分配线程;它几乎肯定会比你更有效率。
-
您提供的代码完全是异步的。如果它阻塞了 UI 线程,那是由于调用堆栈上该方法上方或下方的代码未显示。
-
@Fubak:阅读编译器在
ProcessItem方法上给你的警告。
标签: c# multithreading threadpool asyncfileupload