gpt4 book ai didi

c# - 在延续中使用一个对象,确保它在你需要它之​​前不会被释放

转载 作者:行者123 更新时间:2023-12-05 07:06:27 26 4
gpt4 key购买 nike

在 Xamarin.iOS 应用程序中,出于各种原因我们不能使用 async/await。因此,我们正在使用 Task.ContinueWith。问题是我们在延续中依赖的对象在调用延续之前就被释放了。

using (UIImage image = // Somehow get the image)
{
DoSomethingWith(image);
}

void DoSomethingWithImage(UIImage image)
{
UploadImageAsync(image).ContinueWith(t =>
{
// Image has been disposed by this point.
DisplayResult(t.Result, image);
});
}

我很想知道如何处理上述案例。我考虑过的选项:

  • 删除 using block ,并让 image 超出范围。这将是一个坏主意,因为 UIImage 可能会非常大。
  • 移除using,并在continuation中调用Dispose()。这感觉很容易出错,因为无论哪里存在这样的代码,您都会将对象放置在远离其创建位置的地方。
  • 将对 DoSomethingWithImage() 的调用包装在 Task.Run(() => DoSomethingWithImage(image)).ContinueWith(t => image.Dispose())。所以你有一个延续中的延续。对于这种情况,这感觉过于复杂。
  • 还有其他我忽略的选项吗?

最佳答案

首先,这是一个很好的问题。根据上述选项,我认为您必须更改 angel。

在您当前的实现中,UIImage 的范围与 DoSomethingWith 方法密切相关。换句话说,检索到的图像仅在该方法内部使用。我可以看到两种不同的方式,这将如何演变:

  1. 引入DoSomethingElseWith方法
  2. 摆脱 DoSomethingWith 并“内联” UploadImageDisplayResult

无论哪种方式,您最终都会在 using block 中包含多个方法。这将表明 UIImage 的清理不是方法的责任。在正常情况下,您会通过 await 最后一个并让 using block 完成其工作来完成此操作,对吗?如果您不能等待它,那么继续的最明显选择是使用 ContinueWith。 (其他: TaskFactory.ContinueWhenAll, TaskFactory.ContinueWhenAny, Task.WhenAll, Task.WhenAny, for further info ) .

UIImage image = RetrieveImage();
var uploadJob = UploadImage(image);
var displayJob = uploadJob.ContinueWith((t => DisplayResult(t.Result, image)).Unwrap();
var disposeJob = displayJob.ContinueWith(_ => image.Dispose());

或者,您可以使用一些短信号机制(同步原语)来指示最后一个异步操作何时完成,例如 AutoResetEventCountdownEventTaskCompliitionSource.

您的第三个选择可能是使用 TPL Dataflow 。有了它,您可以将小块组合在一起,并使用 Completion 启动处置作为您的最后一个操作。

关于c# - 在延续中使用一个对象,确保它在你需要它之​​前不会被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62494305/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com