2012-04-07 31 views
2

私は、遅いかもしれないプロパティに対してデータバインディングを使用しています。しかし、私はUIをフリーズしたくありません。代わりに、新しいタスク・ライブラリーを使用したいと考えています。非同期遅延読み込みタスク

理想的には、私の財産は、次のようになります。プロパティは非同期されることはありませんので、

public string MyProperty 
{ 
    get 
    { 
     if (_cache != null) 
     return _cache; 
     var result = await SomeSlowFunction(); 
     return result; 
    } 
} 

しかし、これは現在動作しません。

解決策はありますか?

答えて

1

INotifyPropertyChangedを実装しているとします。そして、多分このような何かは仕事をすることができます。

private string _myProperty; 
public string MyProperty 
{ 
    get 
    { 
     if (_myProperty != null) 
     return _myProperty; 
     MyProperty = Application.Current.Dispatcher.BeginInvoke((Action)(() => SomeSlowFunction())); 
     return string.Empty; 
    } 
    set 
    { 
     if (_myProperty == value) return; 
     _myProperty = value; 
     RaiseNotifyPropertyChanged("MyProperty"); 
    } 
} 
+0

ディスパッチャから来るんしかし:

あなたが「進行中」値のnullを使用する場合は、このような何かを行うことができますか? – user380719

+0

[DispatcherObject.Dispatcher Property](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject.dispatcher.aspx)からのものです。ほとんどのクラスは 'DispatcherObject'から継承されています。 – LPL

+0

[DependencyObject Class](http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.aspx)からMyPropertyを使用してクラスを継承したり、 "Application.Current.Dispatcher"を使用したりできます。 – LPL

0

私は何をすべきか、その後のBackgroundWorkerを呼び出す「作業」realResultのために、それがnullのリターンであるかどうかをチェックします。 BackGroundからのコールバックでrealResultを割り当て、NotifyPropertyChangedを呼び出します。 async onプロパティはほとんど価値がありません。私はBackGroundWorkerの構造と、進行を取り消して報告する能力が好きです。

private System.ComponentModel.BackgroundWorker backgroundWorker1; 
    private string textBackGround; 


    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    public MainWindow() 
    { 
     backgroundWorker1 = new BackgroundWorker(); 
     backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
     backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); 

     InitializeComponent(); 
    } 

    public string TextBackGround 
    { 
     get 
     { 
      if (!string.IsNullOrEmpty(textBackGround)) return textBackGround; 
      backgroundWorker1.RunWorkerAsync(); 
      return "working";    
     } 
    } 

    // This event handler is where the actual, 
    // potentially time-consuming work is done. 
    private void backgroundWorker1_DoWork(object sender, 
     DoWorkEventArgs e) 
    { 
     // Get the BackgroundWorker that raised this event. 
     BackgroundWorker worker = sender as BackgroundWorker; 

     // Assign the result of the computation 
     // to the Result property of the DoWorkEventArgs 
     // object. This is will be available to the 
     // RunWorkerCompleted eventhandler. 
     e.Result = ComputeFibonacci(worker, e); 
    } 

    // This event handler deals with the results of the 
    // background operation. 
    private void backgroundWorker1_RunWorkerCompleted(
     object sender, RunWorkerCompletedEventArgs e) 
    { 
     // First, handle the case where an exception was thrown. 
     if (e.Error != null) 
     { 
      MessageBox.Show(e.Error.Message); 
     } 
     else if (e.Cancelled) 
     { 
      // Next, handle the case where the user canceled 
      // the operation. 
      // Note that due to a race condition in 
      // the DoWork event handler, the Cancelled 
      // flag may not have been set, even though 
      // CancelAsync was called. 
      textBackGround = "Cancelled"; 
      NotifyPropertyChanged("TextBackGround"); 
     } 
     else 
     { 
      // Finally, handle the case where the operation 
      // succeeded. 
      textBackGround = e.Result.ToString(); 
      NotifyPropertyChanged("TextBackGround"); 
     } 
    } 


    // This is the method that does the actual work. For this 
    // example, it computes a Fibonacci number and 
    // reports progress as it does its work. 
    string ComputeFibonacci(BackgroundWorker worker, DoWorkEventArgs e) 
    { 

     // Abort the operation if the user has canceled. 
     // Note that a call to CancelAsync may have set 
     // CancellationPending to true just after the 
     // last invocation of this method exits, so this 
     // code will not have the opportunity to set the 
     // DoWorkEventArgs.Cancel flag to true. This means 
     // that RunWorkerCompletedEventArgs.Cancelled will 
     // not be set to true in your RunWorkerCompleted 
     // event handler. This is a race condition. 

     if (worker.CancellationPending) 
     { 
      e.Cancel = true; 
      return "cancelled"; 
     } 
     Thread.Sleep(1000); 
     if (worker.CancellationPending) 
     { 
      e.Cancel = true; 
      return "cancelled"; 
     } 
     return "complete"; 
    } 
} 
0

BLAMは正しい考えを持っている:あなたはバインディングUIデータはすぐに値を必要とするため、「進行中」、戻り値のいくつかの種類が必要です。ただし、BackgroundWorkerは必要ありません。

// If _cache is not null, then we already have a calculated property value. 
private string _cache; 

// If _cacheTask is not null, then the property is being calculated. 
private Task<string> _cacheTask; 

public string MyProperty 
{ 
    get 
    { 
    if (_cache != null) 
     return _cache; 
    if (_cacheTask != null) 
     return null; // (in progress) 
    StartSomeSlowFunction(); 
    // Note: _cacheTask is not null at this point. 
    return null; // (in progress) 
    } 

    set 
    { 
    if (value == _cache) 
     return; 
    _cache = value; 
    var propertyChanged = PropertyChanged; 
    if (propertyChanged != null) 
     propertyChanged(new PropertyChangedEventArgs("MyProperty")); 
    } 
} 

private async Task StartSomeSlowFunction() 
{ 
    // Immediately start SomeSlowFunction and set _cacheTask. 
    _cacheTask = SomeSlowFunction(); 

    // Asynchronously wait for SomeSlowFunction to complete, 
    // and set the property with the result. 
    MyProperty = await _cacheTask; 

    // Let the task be GCed; this also allows the property to be 
    // recalculated if it is set to null first. 
    _cacheTask = null; 
} 

private async Task<string> SomeSlowFunction(); 
関連する問題