0

実行を継続するには、ある時点で HTTP サーバーからの一意のキーが必要な「ワーカー」がたくさんあります。このキーは、ワーカーが必要とする前に到着することがあります。その場合、ワーカーにキーを提供して、実行を継続できるようにするだけです。ただし、キーが残っていない場合は、キーが提供されるまでタスクでのコード実行を停止したいと考えています。また、最初に提供されたキーを最初に使用することも望んでいます。

HTTP サーバーからキーを提供し、ワーカーがキーを取得できるシングルトンを実装しようとしましたが、現在実行がデッドロックしているようです。

私のコード:

Keyhandler.cs

public sealed class KeyHandler
{
    private static readonly KeyHandler instance = new KeyHandler();

    private static Dictionary<Website, Queue<string>> retrievedKeys = new Dictionary<Website, Queue<string>>();
    private static Dictionary<Website, Queue<TaskCompletionSource<string>>> waitingWorkers = new Dictionary<Website, Queue<TaskCompletionSource<string>>>();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static KeyHandler()
    {
    }

    private KeyHandler()
    {
        foreach (Website website in Enum.GetValues(typeof(Website)))
        {
            retrievedKeys.Add(website, new Queue<string>());
            waitingWorkers.Add(website, new Queue<TaskCompletionSource<string>>());
        }
    }

    public static KeyHandler Instance
    {
        get
        {
            return instance;
        }
    }

    public static void AddKey(Website website, string response)
    {
        if (waitingWorkers[website].Count > 0)
        {
            waitingWorkers[website].Dequeue().SetResult(response);
        }
        else
        {
            retrievedKeys[website].Enqueue(response);
        }
    }

    public static string RetrieveKey(Website website)
    {
        if (retrievedKeys[website].Count > 0)
        {
            return retrievedKeys[website].Dequeue();
        } 
        else
        {
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
            Task<string> t = tcs.Task;
            waitingWorkers[website].Enqueue(tcs);

            return t.Result;
        }
    }
}

Worker.cs

    public async Task Run()
    {
        ...
        string key = KeyHandler.RetrieveKey(Website.MyWebsite);
        // do something with key here
        ...
    }

HTTPServer.cs

private void Process(HttpListenerContext context)
{
    ...
    KeyHandler.AddKey(Website.MyWebsite, key);
    ...
}
4

0 に答える 0