什么时候使用Task.Delay和Thread.Sleep有很好的规则?
我刚刚意识到,在我的代码中的某个地方,我在锁内部有一个return语句.哪一个是最好的?
1)
void example()
{
lock (mutex)
{
//...
}
return myData;
}
Run Code Online (Sandbox Code Playgroud)
2)
void example()
{
lock (mutex)
{
//...
return myData;
}
}
Run Code Online (Sandbox Code Playgroud)
我应该使用哪一个?
从很久以前我想知道确切地存储变量(值类型或引用类型)的位置.它会在堆栈还是堆上?
我也读过Eric Lippert的文章.
出于好奇,我想要的是交叉验证我所理解的内容.任何工具都存在相同的?或者以任何方式我会知道,当.NET程序被执行时,哪些变量存储在堆栈中?哪个存储在堆上?
谢谢
我试图弄清楚到底会ThreadPool.SetMinThreads产生什么影响。
根据官方文件说
设置在切换到管理线程创建和销毁的算法之前,当发出新请求时,线程池按需创建的最小线程数。
根据我的理解,作为一名开发人员,我应该能够控制如何按需旋转新线程的机制,因此它们会被创建并在空闲状态下等待,例如在我期望收到请求负载的情况下在特定时间。
这正是我最初认为SetMinThreads方法的设计目的。
但当我开始实际使用它时 - 我得到了非常奇怪的结果。
所以我有我的 ASP.NET .NET5 应用程序,并且在控制器操作中我有如下代码:
ThreadPool.SetMinThreads(32000, 1000);
当然,我直觉地期望运行时为我创建 32K 工作线程和 1000 个 io 线程。
当我这样做,然后调用其他方法 - Process.GetCurrentProcess().Threads获取所有进程的线程,并打印它们的统计信息,我得到这样的东西
Standby - 17
Running - 4
Run Code Online (Sandbox Code Playgroud)
我认为应用程序可能需要一些时间来旋转新线程,所以我尝试了不同的延迟,1 分钟、5 分钟和 10 分钟。
但结果总是保持不变,我得到15-20 Standby和2-4 Running。
那么接下来的逻辑问题是——SetMinThreads方法到底在做什么?MSDN提供的描述似乎没有太大帮助。
还有另一个逻辑问题 - 如果我想强制 dotnet 在空闲状态下旋转 32K 新线程怎么办 - dotnet 是否为此提供了任何机制?
基于Microsoft MASM 文档,.STACK 指令的用法是
当与 .MODEL 一起使用时,定义一个堆栈段(具有段名称 STACK)。可选大小指定堆栈的字节数(默认为 1,024)。.STACK 指令自动关闭堆栈语句。(仅限 32 位 MASM。)
为了实验,我做了.STACK分配1,073,741,824 bytes (1 GB)
请注意,我在 Visual Studio 2013 控制台项目中运行代码。
.586
.MODEL FLAT
.STACK 1073741824
.DATA
a DWORD 50
b DWORD 55
.CODE
main PROC
addLoop: mov eax, a
push eax
mov eax, 0
mov ebx, b
push ebx
jmp addLoop
RET
main ENDP
END
Run Code Online (Sandbox Code Playgroud)
该代码将溢出堆栈。我所做的是记下ESP寄存器的第一个地址,让代码运行直到溢出,然后ESP从第一个中减去最后一个以获得堆栈的大小。
在我的上下文中,它是00DAFEE4 - 00CB3000 + 1 = 000FCEE5. 这只是1036005 bytes (~1 …
我正在通过 Andrew Troelsen 的书“Pro C# 7 With .NET and .NET Core”学习 C#。在第 19 章(异步编程)中,作者使用了这些示例代码:
static async Task Main(string[] args)
{
Console.WriteLine(" Fun With Async ===>");
string message = await DoWorkAsync();
Console.WriteLine(message);
Console.WriteLine("Completed");
Console.ReadLine();
}
static async Task<string> DoWorkAsync()
{
return await Task.Run(() =>
{
Thread.Sleep(5_000);
return "Done with work!";
});
}
Run Code Online (Sandbox Code Playgroud)
作者接着说
"... this 关键字 (await) 将始终修改返回 Task 对象的方法。当逻辑流到达 await 标记时,调用线程将在此方法中挂起,直到调用完成。如果您要运行此版本在应用程序中,您会发现 Completed 消息显示在 Done with work! 消息之前。如果这是一个图形应用程序,用户可以在 DoWorkAsync() 方法执行时继续使用 UI”。
但是当我在 VS 中运行这段代码时,我没有得到这种行为。主线程实际上被阻塞了 5 秒,直到“完成工作!”之后才会显示“完成”。
查看有关 async/await 如何工作的各种在线文档和文章,我认为“await”会起作用,例如当遇到第一个“await”时,程序会检查该方法是否已经完成,如果没有,它会立即“ …
使用 Parallel.ForEach 时,将任何 DB 或 Api 调用转换为异步方法是否会提高性能?
一些背景知识,我目前有一个控制台应用程序,它按顺序循环访问一堆文件,并为每个文件调用一个 API 并进行一些数据库调用。主要逻辑如下:
foreach (file in files)
{
ReadTheFileAndComputeAFewThings(file);
CallAWebService(file);
MakeAFewDbCalls(file);
}
Run Code Online (Sandbox Code Playgroud)
目前,所有数据库和 Web 服务调用都是同步的。
Parallel.ForEach正如您所期望的那样,更改要使用的循环给我带来了巨大的性能提升。
我想知道是否将调用保留Parallel.ForEach在那里,并在循环内将所有 Web 服务调用更改为异步(例如,HttpClient.SendAsync)并将 DB 调用更改为异步(使用 Dapper,db.ExecuteAsync()) - 这是否会通过允许它来提高应用程序的性能重用线程?或者它实际上什么都不做,因为Parallel.ForEach无论如何都会处理线程分配?
我想限制 C# 中的线程可以分配多少 RAM,这样超出此限制的分配将失败/崩溃或线程将终止。
例如,假设我在 C# 中有 3 个托管线程,即线程 A、B 和 C。我想限制所有三个线程使用不超过 100 MB 的 RAM。如果他们这样做,那么我希望他们崩溃而不影响其他线程。
现在在我看来,由于 C# 是一种基于虚拟机的语言,并且使用垃圾收集器,因此理论上这实际上应该是可能的,而无需尝试使用限制进程 RAM 使用的操作系统功能。
怎样才能实现这样的目标呢?任何指导将不胜感激。
methodX()这两个片段中的执行是否不同?
SemaphoreSlim _locker、.Wait()、 和WaitAsync()是具有同步和异步版本的同一方法的示例:
A:
SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
_locker.Wait();
// .. rest of the code
}
Run Code Online (Sandbox Code Playgroud)
乙:
SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
await _locker.WaitAsync();
// .. rest of the code
}
Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×5
async-await ×2
.net-5 ×1
assembly ×1
asynchronous ×1
callstack ×1
clr ×1
dapper ×1
httpclient ×1
masm ×1
mutex ×1
ram ×1
stack ×1
task ×1
threadpool ×1
vb.net ×1