如果可能,我想为并行启动的任务创建一个异步枚举器。所以第一个完成的是枚举的第一个元素,第二个完成的是枚举的第二个元素,依此类推。
public static async IAsyncEnumerable<T> ParallelEnumerateAsync(this IEnumerable<Task<T>> coldAsyncTasks)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
我打赌有一种使用ContinueWith和 a 的方法Queue<T>,但我并不完全相信自己会实现它。
c# asynchronous task-parallel-library async-await iasyncenumerable
假设我想发出并行 API post 请求。
在 for 循环中,我可以将 http post 调用附加到任务列表中(使用 Task.Run 调用的每个任务),然后等待所有任务完成使用await Task.WhenAll. 因此,在等待网络请求完成时,控制权将交给调用者。实际上,API 请求将并行发出。
同样,我可以使用Parallel.ForEachAsync它将自动执行WhenAll并将控制权返回给调用者。所以我想问是否ForEachAsync可以替换普通的 for 循环列表(async wait Task.Run)和WhenAll?
在遵守一系列约束的同时,我需要生成从0到999999(不重复)的所有可能的数字(整数)。
为了更好地理解要求,请想象每个数字由2位数字的前缀和4位数字的后缀组成。就像000000被读为00-0000和999999被读为99-9999。现在到规则:
到目前为止,我已经写了一些满足所有要求的代码,但第一个除外:
var seed = 102111;
var rnd = new Random(seed);
var prefix = Enumerable.Range(0, 100).OrderBy(p => rnd.Next());
var suffix = Enumerable.Range(0, 10000).OrderBy(s => rnd.Next());
var result = from p in prefix
from s in suffix
select p.ToString("d2") + s.ToString("d4");
foreach(var entry in result)
{
Console.WriteLine(entry);
}
Run Code Online (Sandbox Code Playgroud)
使用这个我可以使用相同的种子来重现序列,前10000个数字的所有数字都从0000到9999,第二个10k等等,但是前缀并不是真正随机的,因为每个10k组都具有相同的前缀。
我还考虑过创建一个带有数字及其组的类(100个组,每个组有1万个数字),以使洗牌更容易,但我认为这是更好,更简单的方法。
我正在尝试从机器发送大量 HTTP 请求。但似乎 .NET Core 或我不知道的 Windows 正在限制可以发出的并发 HTTP 请求的数量,或者给定时间段内 HTTP 请求的配额。
我怎样才能增加这个?我记得我们在 .NET Framework 中有一个配置,但我也找不到。
当我在Visual Studio社区2019(版本16.3.1)中使用Ctrl + F5(无需调试就开始)启动控制台应用程序(.NET Core)时,以下消息将附加在控制台窗口的末尾:
C:\ HelloWorld \ bin \ Debug \ netcoreapp3.0 \ HelloWorld.exe(进程1672)退出,代码为0。
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以防止Visual Studio 2019打印此消息?我尝试通过更改以下选项来防止该解决方案出现在“输出”窗口中,该选项包括:“工具”>“选项”>“调试”>“输出”窗口>“进程退出消息” =“关闭”,但是在控制台窗口中无效。
注意:此消息不会在Visual Studio 2017中显示。它只会在Visual Studio 2019中显示,并且仅在.NET Core应用程序中显示。
编辑:这个问题的要求已经改变。请参阅下面的更新部分。
我有一个异步迭代器方法,它产生一个IAsyncEnumerable<int>(数字流),每 200 毫秒一个数字。此方法的调用者使用流,但希望在 1000 毫秒后停止枚举。因此使用了 a CancellationTokenSource,并且将令牌作为参数传递给WithCancellation扩展方法。但令牌不受尊重。枚举一直持续到所有数字都被消耗完:
static async IAsyncEnumerable<int> GetSequence()
{
for (int i = 1; i <= 10; i++)
{
await Task.Delay(200);
yield return i;
}
}
var cts = new CancellationTokenSource(1000);
await foreach (var i in GetSequence().WithCancellation(cts.Token))
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff} > {i}");
}
Run Code Online (Sandbox Code Playgroud)
输出:
12:55:17.506 > 1
12:55:17.739 > 2
12:55:17.941 > 3
12:55:18.155 > 4
12:55:18.367 > 5
12:55:18.520
: > 572 18 >
18 :55:18.973 > 8 …
我正在使用 来IMemoryCache缓存从身份服务器检索到的令牌。
过去我使用过库GetOrCreateAsync中提供的扩展方法Microsoft.Extensions.Caching.Abstractions。这非常有帮助,因为我可以同时定义函数和到期日期。
但是,使用令牌时,在请求完成之前我不会知道x 秒后的过期值。我想通过根本不缓存令牌来解释不存在的值的用例。
我尝试过以下方法
var token = await this.memoryCache.GetOrCreateAsync<string>("SomeKey", async cacheEntry =>
{
var jwt = await GetTokenFromServer();
var tokenHasValidExpireValue = int.TryParse(jwt.ExpiresIn, out int tokenExpirationSeconds);
if (tokenHasValidExpireValue)
{
cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(tokenExpirationSeconds);
}
else // Do not cache value. Just return it.
{
cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(0); //Exception thrown. Value needs to be positive.
}
return jwt.token;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,当我尝试设置 no time 过期时,会引发异常TimeSpan.FromSeconds(0)。
除了分别调用Get和Set方法之外,还有其他方法可以解决这个问题吗?如果可能的话我想使用该GetOrCreateAsync方法。
我在生产应用程序中描述了https://dotnetfiddle.net/GknA5Q中的以下代码。用作缓存dictionary来保存对象的属性。使用此功能的REST API有数百种对象类型,因此当 API 找到更多对象类型时,缓存会变得更大。正如您在代码中看到的那样,对象的属性是通过反射检索的。当 API 启动并且数百个请求到达 API 时,就会填充这些内容。每个请求都会有一个对象类型,其属性会被缓存。dictionarydictionary
尽管 REST API 可以工作,但当 API 在 IIS 中启动时,代码现在会生成以下错误。生成错误的行号是TryGetValue被调用的23。
更改非并发集合的操作必须具有独占访问权限。对此集合执行并发更新并破坏了其状态。集合的状态不再正确。
我试图在测试应用程序中重现相同的错误,因此可以应用一些解决方案。我不想删除这dictionary会增加处理到达 API 的每个请求中的每个模型的时间。如果该dictionary缓存可用,则可以从缓存中检索属性,而不是通过反射进行解析。
我怎样才能重现上述错误?
我有一个异步方法,说:
public async Task<T> GetAsync()
{
}
Run Code Online (Sandbox Code Playgroud)
并将从以下位置调用:
public async Task<IEnumerable<T>> GetAllAsync()
{
foreach (var item in something)
{
var result = await GetAsync();
yield return result;
}
}
Run Code Online (Sandbox Code Playgroud)
上面的语法无效,但基本上我是在异步生成器之后。我知道它可以通过 Observables 处理。我对 Rx.NET 进行了实验,并且在一定程度上奏效了。但我试图避免它给代码库带来的复杂性,更重要的是,上述需求本质上仍然不是一个反应式系统(我们的仍然是基于拉取的)。例如,我只会在一段时间内收听传入的异步流,并且我必须从消费者端停止生产者(而不仅仅是取消订阅消费者)。
我可以像这样反转方法签名:
public IEnumerable<Task<T>> GetAllAsync()
Run Code Online (Sandbox Code Playgroud)
但这使得在不阻塞的情况下进行 LINQ 操作有点棘手。我希望它是非阻塞的,并且不将整个内容加载到内存中。这个库:AsyncEnumerable正是我正在寻找的,但如何用Ix.NET做到这一点?它们的用途与我相信的相同。
换句话说,我如何利用 Ix.NETIAsyncEnumerable在处理await? 喜欢,
public async IAsyncEnumerable GetAllAsync()
{
foreach (var item in something)
{
var result = await GetAsync();
return // what?
}
}
Run Code Online (Sandbox Code Playgroud) 假设我有一个方法可以运行连续的 while 循环并进行一些异步调用
async Task MethodA(){
while(true){ perform async/await operations }
}
Run Code Online (Sandbox Code Playgroud)
之间有什么区别:
Task.Run( () => MethodA(); }
Task.Run( async () => await MethodA(); }
Run Code Online (Sandbox Code Playgroud)
如果有区别,什么时候一个比另一个更有用?Task.Run 是否以不同的方式对待其每个重载?
c# ×10
.net-core ×3
async-await ×3
asynchronous ×3
linq ×2
.net ×1
algorithm ×1
c#-8.0 ×1
cancellation ×1
collections ×1
concurrency ×1
dictionary ×1
http ×1
memorycache ×1
rx.net ×1