c# – 在后台线程上初始化对象有一个共同的模式吗?
发布时间:2020-12-15 17:27:15 所属栏目:百科 来源:网络整理
导读:我有一个需要很长时间才能初始化的对象.因此,我有能力在应用程序启动时开始初始化.对类的方法的任何后续调用我们需要有一个等待类完成初始化的延迟机制. 我有几个可能的解决方案,但我对它们中的任何一个都不满意.第一个在while循环中使用Task.Delay,第二个使
我有一个需要很长时间才能初始化的对象.因此,我有能力在应用程序启动时开始初始化.对类的方法的任何后续调用我们需要有一个等待类完成初始化的延迟机制.
我有几个可能的解决方案,但我对它们中的任何一个都不满意.第一个在while循环中使用Task.Delay,第二个使用SemaphoreSlim但是涉及一些不必要的阻塞.我觉得这必须是一个相当普遍的要求,任何人都可以就如何最好地管理这个提出一些建议吗? 哦顺便说一句,这是一个Metro应用程序,所以我们有限的API 这是伪代码: public class ExposeSomeInterestingItems { private InitialisationState _initialised; private readonly SemaphoreSlim _waiter = new SemaphoreSlim(0); public async Task StartInitialize() { if (_initialised == InitialisationState.Initialised) { throw new InvalidOperationException( "Attempted to initialise ActiveTrackDown" + "loads when it is already initialized"); } _initialised = InitialisationState.StartedInitialisation; new TaskFactory().StartNew(async () => { // This takes some time to load this._interestingItems = InterestingItemsLoader.LoadItems(); _waiter.Release(); _initialised = InitialisationState.Initialised; }); } public InterestingItem GetItem(string id) { DelayUntilLoaded(); DelayUntilLoadedAlternative(); } private async Task DelayUntilLoaded() { if (_initialised == InitialisationState.NotInitialised) { throw new InvalidOperationException("Error " + "occurred attempting to access details on " + "ActiveTrackDownloads before calling initialise"); } while (true) { if (_initialised == InitialisationState.Initialised) { return; } await Task.Delay(300); } } private async Task DelayUntilLoadedAlternative() { if (_initialised == InitialisationState.NotInitialised) { throw new InvalidOperationException( "Error occurred attempting to access details " + "on ActiveTrackDownloads before calling initialise"); } try { await _waiter.WaitAsync(); } finally { _waiter.Release(); } } } 解决方法
我认为更好的设计是异步工厂,其中调用代码等待对象创建,然后接收常规对象实例.
窃听from Stephen Toub: public class AsyncLazy<T> : Lazy<Task<T>> { public AsyncLazy(Func<T> valueFactory) : base(() => Task.Run(valueFactory)) { } public AsyncLazy(Func<Task<T>> taskFactory) : base(() => Task.Run(taskFactory)) { } public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); } } public static class ExposeSomeInterestingItemsFactory { public static AsyncLazy<ExposeSomeInterestingItems> Instance { get { return _instance; } } private static readonly AsyncLazy<ExposeSomeInterestingItems> _instance = new AsyncLazy<ExposeSomeInterestingItems>(() => new ExposeSomeInterestingItems()); public static void StartInitialization() { var unused = Instance.Value; } } public class ExposeSomeInterestingItems { public ExposeSomeInterestingItems() { // This takes some time to load this._interestingItems = InterestingItemsLoader.LoadItems(); } public InterestingItem GetItem(string id) { // Regular logic. No "delays". } } ... var exposeSomeInterestingItems = await ExposeSomeInterestingItemsFactory.Instance; var item = exposeSomeInterestingItems.GetItem("id"); 这样,您就可以很好地遵守单一责任原则: > AsyncLazy< T>结合任务< T>与Lazy< T> (因此仅在需要时才异步创建实例). 此外,此解决方案始终是异步的(无阻塞),这很好(特别是对于Metro应用程序). 更新,2012-09-14:我已经使用了这段代码并将其清理干净并将其评论为on my blog. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |