在多线程中,线程共享一些东西,但不共享局部变量。每个线程维护其自己的堆栈副本,该副本存储本地变量。很好,但是在这种情况下会发生什么?
public async Task<string> ReadFile()
{
var fileName = GenerateFileName();
using (var reader = File.OpenText(fileName))
{
var fileText = await reader.ReadToEndAsync();
return fileName + "|" + fileText;
}
}
当IO操作开始时,线程进入睡眠状态(或执行其他操作),而当线程(或其他线程)返回以继续执行该功能时,它如何记住fileName
的值?堆栈在这里发生了什么?
答案 0 :(得分:3)
它的发生方式与yield
方法存储其本地变量的方式类似:它创建一个struct
,该变量具有C#中本地变量作为字段。
因此,如果aysnc
不存在,您的代码将产生某些编码,例如:
private struct ReadFileAsyncStateMachine : IAsyncStateMachine
{
public int _state;
public AsyncTaskMethodBuilder<string> _builder;
private string _fileName;
private string _fileText;
private StreamReader _reader;
TaskAwaiter<string> _awaiter;
void IAsyncStateMachine.MoveNext()
{
try
{
if (_state != 0)
{
goto afterSetup;
}
_fileName = GenerateFileName();
_reader = File.OpenText(_fileName);
TaskAwaiter<string> awaiter = _reader.ReadToEndAsync().GetAwaiter();
_state = -1;
if (!awaiter.IsCompleted)
{
_awaiter = awaiter;
_builder.AwaitUnsafeOnCompleted<TaskAwaiter<string>, ReadFileAsyncStateMachine>(ref awaiter, ref this);
return;
}
afterSetup:
awaiter = _awaiter;
_fileText = awaiter.GetResult();
_state = -2;
_builder.SetResult(_fileName + "|" + _fileText);
_reader.Dispose();
}
catch (Exception exception)
{
_state = -2;
_builder.SetException(exception);
_reader?.Dispose();
return;
}
}
[DebuggerHidden]
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine param0)
{
_builder.SetStateMachine(param0);
}
}
public Task<string> ReadFile()
{
ReadFileAsyncStateMachine stateMachine = new ReadFileAsyncStateMachine();
AsyncTaskMethodBuilder<string> builder = AsyncTaskMethodBuilder<string>.Create();
stateMachine._builder = builder;
stateMachine._state = -1;
builder.Start(ref stateMachine);
return builder.Task;
}
ReadFileAsyncStateMachine
处理ReadToEndAsync()
立即完成的可能性,在这种情况下,返回的Task<string>
立即完成并且有结果或正在运行,在这种情况下,{{1返回的}}本身正在运行,随后对Task<string>
的调用将完成它。异常也得到处理。
如您所见,C#中的本地语言是实现中的字段。