0

メソッド GetData を持つクラスが与えられます。他のいくつかのクライアントが GetData を呼び出し、毎回データを取得する代わりに、最初の呼び出しでタスクを開始してデータを取得し、残りの呼び出しでタスクが完了するまで待機するパターンを作成したいと考えています。

private Task<string> _data;
private async Task<string> _getdata()
{
    return "my random data from the net"; //get_data_from_net()
}
public string GetData()
{
    if(_data==null)
        _data=_getdata();

    _data.wait(); //are there not a problem here. cant wait a task that is already completed ? if(_data.status != rantocompletion) _data.wait() is not any better, it might complete between the check and the _data.wait?


    return _data.Result;
}

パターンを正しく行うにはどうすればよいですか?

(解決)

    private static object _servertime_lock = new object();
    private static Task<string> _servertime;
    private static async Task<string> servertime()
    {
        try
        {
            var thetvdb = new HttpClient();
            thetvdb.Timeout = TimeSpan.FromSeconds(5);
            // var st = await thetvdb.GetStreamAsync("http://www.thetvdb.com/api/Updates.php?type=none");
            var response = await thetvdb.GetAsync("http://www.thetvdb.com/api/Updates.php?type=none");
            response.EnsureSuccessStatusCode();
            Stream stream = await response.Content.ReadAsStreamAsync();
            XDocument xdoc = XDocument.Load(stream);
            return xdoc.Descendants("Time").First().Value;
        }
        catch
        {
            return null;
        }
    }
    public static async Task<string> GetServerTime()
    {
        lock (_servertime_lock)
        {
            if (_servertime == null)
                _servertime = servertime();
        }

        var time = await _servertime;
        if (time == null)
            _servertime = null;

        return time;

    }
4

2 に答える 2

0

最初の呼び出しでタスクを開始してデータを取得し、残りの呼び出しでタスクが完了するまで待機するパターンを作成したいと考えています。

私のブログで説明されているように、非同期遅延初期化を使用することをお勧めします。型はAsyncLazy<T>、記述する必要があるコードを簡素化します。

private readonly AsyncLazy<string> _data = new AsyncLazy<string>(async () =>
{
  return "my random data from the net"; //get_data_from_net()
});

public Task<string> GetData()
{
  return await _data;
}

または、クライアントがすべてasyncの場合は、次のようにすることができます。

public AsyncLazy<string> Data { get; private set; }

Constructor()
{
  Data = new AsyncLazy<string>(async () =>
  {
    return "my random data from the net"; //get_data_from_net()
  });
}

そして、クライアントはこれを行うことができます:

var data = await my.Data;
于 2012-10-15T15:09:58.477 に答える
0

Wait()2 回呼び出しても問題はありません。2 番目の呼び出しは何もしません。
実際、タスクが完了していない場合、Resultプロパティは暗黙的に呼び出されます。Wait()

補足としてGetData()、呼び出し元が待機するタイミングまたは待機するかどうかを決定できるように、非同期にすることも検討する必要があります。

コードはスレッドセーフではないことに注意してください。複数のスレッドから呼び出される可能性がある
場合は、クラスを使用する必要があります。 GetData()Lazy<T>

于 2012-10-15T02:44:00.597 に答える