相关疑难解决方法(0)

Dapper QueryAsync首次阻止UI(针对Oracle服务器)?

首先,我认为第一次只是更清楚地看到阻塞的条件.对于下一次,它会以某种方式稍微阻止UI,但不会像不使用异步时那样明显.

我可以这么说,因为我可以看到使用它QueryAsync和一个简单的包装代码之间的区别,Task.Run(() => connection.Query<T>)它的工作正常,当然比QueryAsync(在UX中)要好得多.

代码很简单,就像这样:

public async Task<IEnumerable<Item>> LoadItemsAsync(){
  using(var con = new OracleConnection(connectionString)){
     var items = await con.QueryAsync<dynamic>("someQuery");
     return items.Select(e => new Item { ... });
  }
}
//in UI thread, load items like this:
var items = await LoadItemsAsync();
Run Code Online (Sandbox Code Playgroud)

代码工作正常(没有阻止UI)是这样的:

public async Task<IEnumerable<Item>> LoadItemsAsync(){
  using(var con = new OracleConnection(connectionString)){
     var items = await Task.Run(() => con.Query<dynamic>("someQuery"));
     return items.Select(e => new Item { ... });
  }
}
//in UI …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous blocking dapper

9
推荐指数
1
解决办法
775
查看次数

异步I/O密集型代码比非异步运行得慢,为什么?

我正在重构一个应用程序,并尝试添加现有函数的异步版本,以提高ASP.NET MVC应用程序的性能时间.我知道异步函数有一个开销,但我预计,如果有足够的迭代次数,从数据库加载数据的I/O密集型性质将不仅可以弥补开销损失,而且还可以获得显着的性能提升.

TermusRepository.LoadByTermusId函数通过从数据库中检索一堆数据表(使用ADO.NET和Oracle Managed Client)来加载数据,填充模型并返回它.TermusRepository.LoadByTermusIdAsync类似的,除了它是异步的,当有多个数据表需要检索时,加载数据表下载任务的方法略有不同.

public async Task<ActionResult> AsyncPerformanceTest()
{
    var vm = new AsyncPerformanceTestViewModel();
    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int i = 0; i < 60; i++)
    {
        TermusRepository.LoadByTermusId<Termus2011_2012EndYear>("1");
        TermusRepository.LoadByTermusId<Termus2011_2012EndYear>("5");
        TermusRepository.LoadByTermusId<Termus2011_2012EndYear>("6");
        TermusRepository.LoadByTermusId<Termus2011_2012EndYear>("7");
    }
    watch.Stop();
    vm.NonAsyncElapsedTime = watch.Elapsed;
    watch.Reset();
    watch.Start();
    var tasks = new List<Task<Termus2011_2012EndYear>>();
    for (int i = 0; i < 60; i++)
    {
        tasks.Add(TermusRepository.LoadByTermusIdAsync<Termus2011_2012EndYear>("1"));
        tasks.Add(TermusRepository.LoadByTermusIdAsync<Termus2011_2012EndYear>("5"));
        tasks.Add(TermusRepository.LoadByTermusIdAsync<Termus2011_2012EndYear>("6"));
        tasks.Add(TermusRepository.LoadByTermusIdAsync<Termus2011_2012EndYear>("7"));               
    }
    await Task.WhenAll(tasks.ToArray());
    watch.Stop();
    vm.AsyncElapsedTime = watch.Elapsed;            
    return View(vm);
}

public static async Task<T> LoadByTermusIdAsync<T>(string …
Run Code Online (Sandbox Code Playgroud)

c# oracle asynchronous async-await

6
推荐指数
2
解决办法
2149
查看次数

从 IEnumerable&lt;Task&lt;T&gt;&gt; 到 IAsyncEnumerable&lt;T&gt; 通过在 Parallel.ForEach/Parallel.ForEachAsync 内返回的yield 给出错误 CS1621

在 .NET 6 项目中,我必须调用一个偏移分页(页/每页)的 Web API,并且我希望尽可能使 n 个调用并行。

这是使用给定页码调用 API 一次的方法:

private Task<ApiResponse> CallApiAsync(int page,
    CancellationToken cancellationToken = default)
{
    return GetFromJsonAsync<ApiResponse>($"...&page={page}", cancellationToken)
        .ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

我实际上需要的是从第 1 页到第 n 页的所有 API 调用的仅前向流式迭代器,因此考虑到这一要求,我认为这IAsyncEnumerable是正确的 API,这样我就可以并行触发 API 调用并访问每个 API 响应一旦准备好,就可以完成,而不需要全部完成。

所以我想出了以下代码:

public async IAsyncEnumerable<ApiResponse> CallApiEnumerableAsync(int perPage,
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    int numProducts = GetNumberOfProducts(perPage);

    int numCalls = MathExtensions.CeilDiv(numProducts, perPage);

    var pages = Enumerable.Range(1, numCalls);

    Parallel.ForEach(pages, async page => {
        yield return await CallApiAsync(page, cancellationToken).ConfigureAwait(false);
    });

    yield break;
}
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误 …

c# parallel.foreach .net-core iasyncenumerable parallel.foreachasync

3
推荐指数
1
解决办法
300
查看次数