TaskEx.Run
UI に戻ってロード中のグラフィックを表示できるように、Linq-To-SQL を使用してデータベースを大量に呼び出しています。一部のデータを ViewModel にロードします。
それは最初に起動されたときに機能しますが、通常は 3 回目 (場合によってはそれ以上) までに起動し、それがオンになっているスレッドが「失われた」か、ディスパッチャが再び実行に戻らないかのように、決して完了しません。も例外ではありません。
UI をアクティブにしてコードを再度実行すると、さらに 3 回ほど動作します。
デバッガーを使用しましたが、通常、継続コードの途中で実行トレースが消えます。
Microsoft.Bcl.Async
これは、ライブラリを使用する Windows Phone 7.5 プロジェクト用です。
ここにコードがあります、
public async Task LoadConversionsPageDataAsyncTask(int profileId, ConversionId conversionId)
{
// Fire the event off
this.IsConversionDataLoading = true;
if (this.ConversionDataLoading != null)
this.ConversionDataLoading(this);
// Load up the data in case of tombstone situation
if (App.VM.SelectedProfile == null || App.VM.SelectedProfile.Id != profileId)
App.VM.SelectedProfile = (from Profile p in App.VM.appDB.Profiles where p.Id == profileId select p).FirstOrDefault();
if (App.VM.SelectedConversionType != conversionId)
App.VM.SelectedConversionType = conversionId;
// TODO: If gender not specified, then return Female measurements. Note only perform gener query on tables that have
// Gender fields (even after casting) because it still generate SQL to query gender
GenderId qGender = (this.SelectedProfile.Gender == GenderId.Unspecified) ? GenderId.Female : this.SelectedProfile.Gender;
this.LoadRequiredMeasurements(qGender, this.SelectedConversionType);
Dictionary<MeasurementId, double> measuredVals = this.ConversionMeasurements.ToDictionary(k => k.MeasurementId, v => Double.Parse(v.Value));
// Check we have all the necessary measurements
if (measuredVals == null) return;
// Build up by regions
RegionId selectedRegion = this.SelectedRegion;
this.GroupedConversions = await TaskEx.Run(() =>
{
// Do database (Linq-to-sql) stuff first, so this should translate to SQL and run SQL with AsList
List<ConversionData> conversions = (from d in conversiondsDB.ConversionData
where d is ConversionData
// Filter to specific region, gender, conversion
&& d.Region == selectedRegion
&& d.Gender == qGender
&& d.Conversion == this.SelectedConversionType
&& !this.BlacklistedBrands.Contains(d.Brand)
select d).ToList();
conversions.Sort((a, b) => { return a.BrandName.CompareTo(b.BrandName); });
// Group up the brand names
string groupKeys = "#abcdefghijklmnopqrstuvwxyz";
// Initially store in a dictionary
Dictionary<string, List<ConversionData>> groupDict = new Dictionary<string, List<ConversionData>>();
foreach (char c in groupKeys)
{
groupDict.Add(c.ToString(), new List<ConversionData>());
}
foreach (ConversionData cd in conversions)
{
// Find the best fit whilst at it
cd.FindBestFit(measuredVals);
// Add to the right group according to the first letter of the brand name
char key = char.ToLower(cd.BrandName[0]);
if (key < 'a' || key > 'z') key = '#';
groupDict[key.ToString()].Add(cd);
}
// Buffer first to avoid triggering the NotifyPropertyChanged events on ObservableCollection hundreds of times
List<LongListSelectorGroup<ConversionData>> buff = new List<LongListSelectorGroup<ConversionData>>();
foreach (char key in groupKeys)
{
string k = key.ToString();
buff.Add(new LongListSelectorGroup<ConversionData>(k, groupDict[k]));
}
return new ObservableCollection<LongListSelectorGroup<ConversionData>>(buff);
});
// Fire the end event
if (this.ConversionDataLoaded != null)
this.ConversionDataLoaded(this);
this.IsConversionDataLoading = false;
}
OnNavigatedTo
イベントの呼び出しコードは次のとおりです
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.AdRotatorControl.Invalidate();
base.OnNavigatedTo(e);
// Load up the data using a query string in case of tombstoning
string profileIdStr, conversionIdStr;
NavigationContext.QueryString.TryGetValue("ProfileId", out profileIdStr);
int profileId = System.Int32.Parse(profileIdStr);
NavigationContext.QueryString.TryGetValue("ConversionId", out conversionIdStr);
ConversionId conversionId = (ConversionId)Enum.Parse(typeof(ConversionId), conversionIdStr, true);
if (App.VM.GroupedConversions == null
|| !App.VM.SkipLoadConversionPageData)
{
App.VM.LoadConversionsPageDataAsyncTask(profileId, conversionId);
}
if (App.VM.SkipLoadConversionPageData)
App.VM.SkipLoadConversionPageData = false;
}