Task.Run 只同步运行?

问题描述 投票:0回答:1

我正在尝试编写一种读取 pdf 每一页的方法,但由于通过 api 读取每一页需要花费大量时间,而且我正在查看数百页长的 pdf,因此我想将异步读取每个页面,然后在准备好时返回结果,因此一次读取多个页面。

我使用 Task.Run 对任务进行“排队”,我希望看到调试日志不按顺序打印页面,但它们只按顺序执行,所以我认为它们是同步运行的。有什么想法吗?

var tasks = new List<Task>();
foreach (Page page in _pdfDoc.GetPages()) {
    var task = Task.Run(() => {
        //tried adding await Task.Yield() here, doesn't work
        Debug.WriteLine("searching page " + page.Number);
        if (page.Text.Contains(query)) {
            pagesWithQuery.Add(page.Number);
        }
        howManySearched += 1;
        Dispatcher.UIThread.InvokeAsync(() => {
            searchProgress.Value = howManySearched;
        });
        return Task.CompletedTask;
    });
    tasks.Add(task);
    // await task; <== does nothing??
}
// await Task.WhenAll(tasks); <== also nothing
c# asynchronous async-await task
1个回答
0
投票

我使用

Task.Run
“排队”任务,我希望看到调试日志不按顺序打印页面,但它们只按顺序执行,所以我认为它们是同步运行的。

您没有足够的数据来支持这个假设。您仅记录每个

Task
:

的开头
Task task = Task.Run(() =>
{
    Debug.WriteLine("searching page " + page.Number);

...但你不知道

Task
何时完成。通过执行以下操作,您可以更好地了解代码实现的并发级别:

object locker = new();
int concurrencyCounter = 0;
int maxConcurrency = 0;

Task task = Task.Run(() =>
{
    Debug.WriteLine("searching page " + page.Number);
    int concurrency = Interlocked.Increment(ref concurrencyCounter);
    lock (locker) maxConcurrency = Math.Max(maxConcurrency, concurrency);
    try
    {

        // Do work with the PDF page...

    } finally { Interlocked.Decrement(ref concurrencyCounter); }
});

//...

await Task.WhenAll(tasks);
Debug.WriteLine($"Maximum concurrency: {maxConcurrency}");

顺便说一句,您的代码中有大量惯用语。您没有利用

Parallel
类或
AsParallel
PLINQ 运算符,也没有利用
Progress<T>
类,而且我怀疑使用未识别的
howManySearched 还存在竞争条件
pagesWithQuery
变量。

© www.soinside.com 2019 - 2024. All rights reserved.