强制异步方法被调用一次 [英] Enforce an async method to be called once

查看:127
本文介绍了强制异步方法被调用一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个需要使用InitializeAsync()方法执行一些异步初始化的类。
我想确保初始化仅执行一次。如果初始化过程正在进行时另一个线程调用此方法,它将等待直到第一个调用返回。

Say I have a class that needs to perform some async initialization using an InitializeAsync() method. I want to make sure that the initialization is performed only once. If another thread calls this method while the initalization is already in progress, it will "await" until the first call returns.

我正在考虑以下实现(使用SemaphoreSlim )。
是否有更好/更简单的方法?

I was thinking about the following imlementation (using SemaphoreSlim). Is there a better/simpler approach?

public class MyService : IMyService
{
    private readonly SemaphoreSlim mSemaphore = new SemaphoreSlim(1, 1);
    private bool mIsInitialized;

    public async Task InitializeAsync()
    {
        if (!mIsInitialized)
        {
            await mSemaphore.WaitAsync();

            if (!mIsInitialized)
            {
                await DoStuffOnlyOnceAsync();
                mIsInitialized = true;
            }

            mSemaphore.Release();
        }
    }

    private Task DoStuffOnlyOnceAsync()
    {
        return Task.Run(() =>
        {
            Thread.Sleep(10000);
        });
    }
}

谢谢!

编辑:

由于我使用的是DI,因此该服务将被注入,以懒惰的形式使用资源或使用异步工厂对我不起作用(尽管在其他用例中可能很棒)。
因此,异步初始化应该封装在类中,并且对 IMyService 使用者透明。

Since I'm using DI and this service will be injected, consuming it as a "Lazy" resource or using an async factory won't work for me (although it could be great in other use cases). Thus, the async initialization should be encapsulated within the class and transparent to the IMyService consumers.

将初始化代码包装在虚拟 AsyncLazy<> 对象中的想法可以完成这项工作,尽管对我来说感觉有点不自然。

The idea of wrapping the initialization code in a "dummy" AsyncLazy<> object will do the job, although it feels a bit unnatural to me.

推荐答案

我会选择 AsyncLazy< T> (略作修改的版本):

I'd go with AsyncLazy<T> (slightly modified version):

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(); } 
}

private AsyncLazy<bool> asyncLazy = new AsyncLazy<bool>(async () =>
                                    { 
                                        await DoStuffOnlyOnceAsync()
                                        return true;
                                    });

请注意,我之所以使用 bool 仅仅是因为您没有 DoStuffOnlyOnceAsync 的返回类型。

Note i'm using bool simply because you have no return type from DoStuffOnlyOnceAsync.

编辑:

Stephan Cleary(当然)也有一个工具此处

Stephan Cleary (of course) also has an implementation of this here.

这篇关于强制异步方法被调用一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆