【发布时间】:2023-04-02 20:37:01
【问题描述】:
我正在尝试创建一个序列化接口(类似于 Cocoa 的NSCoding 协议),以便我可以快速获得一个类的二进制表示,以通过网络发送或存储在数据库中。但是,某些情况(尤其是涉及图像编码)有许多需要awaiting 的仅异步方法。但是,如果字节没有按顺序写入,那么整个表示当然会被破坏。在继续下一个对象之前,我必须确保当前对象已完成序列化。这是我正在做的主要循环。
public async static Task<byte[]> Serialize(this IList<ISerializable> list) {
using (Archiver archiver = new Archiver()) {
archiver.Write(list.Count);
foreach (ISerializable value in list) {
await archiver.Write(value);
}
return archiver.Result;
}
}
Archiver 只是在底层使用MemoryStream 和BitmapWriter 写入BinaryWriter 可以直接接受的值或ISerializable 对象,然后将结果作为字节数组输出。 ISerializable 只是一个带有两个方法(Serialize 和 Deserialize)的接口。他们都返回Task,以便他们可以成为awaited。问题是当我有一个没有任何异步组件的序列化方法时。我可以做以下两件事之一:
A)无论如何,我都可以在该类的序列化方法上添加async,并忍受编译器警告说它将同步执行(我不喜欢编译器警告)。
B) 在方法结束时手动返回一个空任务 (return Task.Run(() => {});)。然而,这看起来和闻起来真的很奇怪。
A 和 B 似乎执行起来都没有问题,但是这种方法是否存在我可能遗漏的问题?我不知道 Windows 运行时中的二进制序列化程序(我包含标签只是为了消除任何混淆)。也许我可以考虑一个选项C?实际上我不想让序列化方法异步,但由于某种原因,task.Wait() 没有等待,而且我在尝试使用用 CreateAsync 创建的对象之前得到了一个空引用异常。
编辑我想到了一个选项 C。我可以将整个方法包装在一个 await Task.Run(...) 调用中。这正常吗?
【问题讨论】:
-
你可以等待Task.Delay(0),它会立即返回。
-
@HansPassant 我更喜欢那个解决方案^^
-
你的图片处理是第三方库吗?我问是因为在我看来,图像编码(和一般的序列化)不是自然的
async操作。也就是说,我更喜欢@svick 的解决方案,它类似于选项 B,开销更少。 -
@StephenCleary 不,只是普通的 BitmapEncoder 东西,但是所有将其转换为流和东西的调用都是异步的,我找不到其他方法来替换它们。例如,我在 WinRT 上找不到与
stream.ReadAsync等效的Stream.Read,而创建BitmapEncoder类的唯一方法是通过其CreateAsync方法。
标签: c# asynchronous windows-runtime c#-5.0 async-await