0

たとえば、.NET 4.5 非同期タスク メソッドがあるとします。

 public async Task<String> GetData()

 (...)

 return await MyObject.GetSomethingAsynchronous();

そして、同期スレッド (非同期でないメソッドなど) の別の場所で、次のように呼び出します。

 String myString = MyObject.GetData().Result;

これは安全に実行できますか、それとも悪い習慣ですか?

4

2 に答える 2

2

通話Task.Resultは基本的にお勧めしません。より良い解決策はawaitTaskを含むメソッドを に変更してasync、非同期コードがコード ベースを通じて成長できるようにすることです。

Task.Resultと比較して2 つの問題がありますawait(非同期に待機するのではなく、ブロックするという事実以外に):

  1. Taskが特定のスレッド (UI スレッドなど) を完了する必要があるにもかかわらず、そのスレッドが でブロックされているというデッドロック状態に簡単に陥る可能性がありますTaskこれについては、ブログで詳しく説明しています。
  2. メソッドからスローされたエラーasyncは でラップされるためAggregateException、例外処理がより複雑になります。awaitは、根本的なエラーをアンラップし、より自然な を使用できるようにしますcatch(MyExceptionType)
于 2012-12-17T14:46:41.007 に答える
0

基本的にはい。

あなたの質問から、どれが必ずしも正しいとは限らないと考えているかがTaskわかりsomething executed in separate threadました。Asycメカニズムはそれよりも一般的であり、スレッドが1つとして終了する、Webリクエストが値を返す、ファイルシステムがファイルを読み取る、その他必要なことを待機している間、その間に何かを行うことができます。これは、次のようなパターンに煩わされないようにするための凝った構文糖衣に他なりません。

void DoSomethingTimeConsumingThatWillNotBlockThisThread(Action onFinishContinue);

次の簡単なプログラムを検討してください。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        GetPoint();
    }

    public async void GetPoint()
    {
        var point = await RetrivePointAsync();
        MessageBox.Show(point.ToString());
    }

    public Task<Point> RetrivePointAsync()
    {
        return Task.Factory.FromAsync<Point>(
             (callback, state) => new Handler(this, callback),
             x => ((Handler)x).Point, null);
    }
}

私がイベントに添付した私の主張を証明するために、ユーザーがクリックするのを待っているので、スレッドは関係ありません。

class Handler : IAsyncResult
{
    AsyncCallback _calback;
    public Point Point { get; set; }
    public object AsyncState { get { return null; } }
    public bool CompletedSynchronously { get { return false; } }
    public bool IsCompleted { get; set; }

    public WaitHandle AsyncWaitHandle { get { return null; } }

    public Handler(Control control, AsyncCallback calback)
    {
        _calback = calback;
        control.MouseDown += control_MouseDown;
    }

    void control_MouseDown(object sender, MouseEventArgs e)
    {
        Point = e.Location;
        IsCompleted = true;
        _calback(this);
    }
}
于 2012-12-17T05:18:12.813 に答える