事件触发时完成任务
Complete a task when an event fires
这应该很简单,但我就是无法聚焦。
在这个方法中
public static async Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => //signal the task to complete and return assemblyName
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
}
if (silentFail)
{
return null;
}
else
{
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}
}
AssemblyLoadContext.Unload()
操作实际上是异步的,但不可等待。一旦没有更多的强 GC 引用等操作完成,程序集卸载并触发卸载事件。
return 值在 assemblyName
中,我想提供给后续。
我能找到的所有文档都在喋喋不休地谈论 await
的必要性,因为这是 yield 发生的地方,但我不能那样写。没有 await
怎么办?
您正在寻找 TaskCompletionSource<string>
:
public static Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var tcs = new TaskCompletionSource<string>();
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
return tcs.Task;
}
if (silentFail)
{
return Task.FromResult<string>(null);
}
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}
}
请注意,如果这抛出一个 InvalidOperationException
,它会在调用 UnloadAsync
时被抛出,而不是被包裹在返回的 Task
中(如果您的方法会发生这种情况是 async
)。如果你想改变这个,你可以使用 TaskCompletionSource:
public static Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
var tcs = new TaskCompletionSource<string>();
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
}
else if (silentFail)
{
tcs.SetResult(null);
}
else
{
tcs.SetException(throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?"));
}
return tcs.Task;
}
或使用async
方法:
public static async Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var tcs = new TaskCompletionSource<string>();
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
return await tcs.Task;
}
if (silentFail)
{
return null;
}
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}
这应该很简单,但我就是无法聚焦。
在这个方法中
public static async Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => //signal the task to complete and return assemblyName
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
}
if (silentFail)
{
return null;
}
else
{
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}
}
AssemblyLoadContext.Unload()
操作实际上是异步的,但不可等待。一旦没有更多的强 GC 引用等操作完成,程序集卸载并触发卸载事件。
return 值在 assemblyName
中,我想提供给后续。
我能找到的所有文档都在喋喋不休地谈论 await
的必要性,因为这是 yield 发生的地方,但我不能那样写。没有 await
怎么办?
您正在寻找 TaskCompletionSource<string>
:
public static Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var tcs = new TaskCompletionSource<string>();
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
return tcs.Task;
}
if (silentFail)
{
return Task.FromResult<string>(null);
}
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}
}
请注意,如果这抛出一个 InvalidOperationException
,它会在调用 UnloadAsync
时被抛出,而不是被包裹在返回的 Task
中(如果您的方法会发生这种情况是 async
)。如果你想改变这个,你可以使用 TaskCompletionSource:
public static Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
var tcs = new TaskCompletionSource<string>();
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
}
else if (silentFail)
{
tcs.SetResult(null);
}
else
{
tcs.SetException(throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?"));
}
return tcs.Task;
}
或使用async
方法:
public static async Task<string> UnloadAsync(Assembly assy, bool silentFail = false)
{
if (AssyLoadContext.__alcd.ContainsKey(assy))
{
var tcs = new TaskCompletionSource<string>();
var assemblyName = __namd.Where(kvp => kvp.Value == assy).First().Key;
__alcd[assy].Unloading += alc => tcs.SetResult(assemblyName);
__namd.Remove(assemblyName);
__alcd[assy].Unload();
__alcd.Remove(assy);
Debug.WriteLine($"Unloaded assembly '{assy.GetName().Name}'");
return await tcs.Task;
}
if (silentFail)
{
return null;
}
throw new InvalidOperationException($"Assembly '{assy.GetName().Name}' cannot be unloaded. Did you load it using AssyLoadContext.LoadWithPrivateContext(string assyPath)?");
}