繁体   English   中英

事件触发时完成任务

[英]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 引用等操作完成,程序集就会卸载并触发 Unloading 事件。

返回值在我想提供给延续的assemblyName中。

我能找到的所有文档都在谈论需要await ,因为那是收益发生的地方,但我不能那样写。 你如何在没有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)?");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM