初期化に時間がかかるオブジェクトがあります。したがって、アプリケーションの起動時に初期化を開始する機能があります。クラスのメソッドへの後続の呼び出しには、クラスの初期化が完了するのを待機する遅延メカニズムが必要です。
私にはいくつかの解決策がありますが、どちらにも完全に満足しているわけではありません。1つ目はwhileループでTask.Delayを使用し、2つ目は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();
}
}
}