protected override void OnRequestSlowData(int index) { if (_pendingPictureAcquires.ContainsKey(index)) { return; } SlowDataResult result = new SlowDataResult(); result.Index = index; _pendingPictureAcquires[index] = result; Microsoft.MediaCenter.UI.Application.DeferredInvokeOnWorkerThread(AcquireSlowData, StoreSlowData, result); }
private static void AcquireSlowData(object args) { //ThreadPriority priority = Thread.CurrentThread.Priority; try { //Thread.CurrentThread.Priority = ThreadPriority.Lowest; SlowDataResult result = (SlowDataResult)args; result.PicturePath = @"\ProgramData\My Movies\Covers\tmb5cb25864-26c1-4b24-86b4-93d724e815fa.jpg"; } finally { //Thread.CurrentThread.Priority = priority; } }
// // Slow data is ready. // // This call occurs after the worker thread is complete and the results // are ready. // // NOTE: THIS CALL CAN HAPPEN AFTER THE VIRTUAL LIST HAS BEEN DISPOSED. // // Take care during this type of callback. It's asynchronous and you can't // make assumptions about the validity of the virtual list (or the data items // within it). // private void StoreSlowData(object args) { SlowDataResult result = (SlowDataResult)args; // // Remove tracking for pending picture acquires. // _pendingPictureAcquires.Remove(result.Index); // // If the VirtualList has been disposed before this callback is received, // or if the data item specified by the index has been thrown away, then // clean up the picture file. // // Note that we need to check IsItemAvailable() instead of just calling // the indexer and checking for null. This is because doing that query // can cause the item to be faulted in after it'd already been thrown // away due to going offscreen. // if (IsDisposed || !IsItemAvailable(result.Index)) { if (result.PicturePath != null) { File.Delete(result.PicturePath); } return; } // // All is well, tell the ThumbnailData about this new picture. // ThumbnailData t = (ThumbnailData)this[result.Index]; t.SetPicture(result.PicturePath); }
private void StoreSlowData(object args) { SlowDataResult result = (SlowDataResult)args; _pendingPictureAcquires.Remove(result.Index); if (IsDisposed || !IsItemAvailable(result.Index)) { if (result.PicturePath != null) { ////File.Delete(result.PicturePath); } return; } MovieItem t = (MovieItem)this[result.Index]; t.DefaultImage = new Image("file://" + result.PicturePath); //t.SetPicture(result.PicturePath); }
// // Acquire the slow data. // // THIS CALL HAPPENS ON A WORKER THREAD. Never call any MCML object from a // worker thread. // private static void AcquireSlowData(object args) { // // Heavy operation: Build our randomly-generated snow flake image. // ThreadPriority priority = Thread.CurrentThread.Priority; try { Thread.CurrentThread.Priority = ThreadPriority.Lowest; SlowDataResult result = (SlowDataResult)args; FractalSnow.SnowFlake flakeGenerator = new FractalSnow.RandomSnowFlake(100, result.Index); flakeGenerator.Antialiasing = true; System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(100, 100); System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap); flakeGenerator.Draw(graphics, new System.Drawing.PointF(50, 50)); string flakePicture = Path.GetTempPath() + result.Index.ToString(CultureInfo.InvariantCulture) + "." + TempPictureFileExtension; bitmap.Save(flakePicture, System.Drawing.Imaging.ImageFormat.Png); graphics.Dispose(); bitmap.Dispose(); // // The locatation of the generated file // result.PicturePath = flakePicture; } finally { Thread.CurrentThread.Priority = priority; } }
// // Slow Data Request // // In the recommended configuration, a data item will always be returned // quickly from OnRequestItem. This data may be partially complete. In // which case, the rest of the data needs to be acquired. // // This callback is enabled using 'EnableSlowDataRequests'. Technically, // you can acquire your own slow data and finish off your data items // on your own time. But, the benefit of using this callback is that // the platform will inform you of prior requested items that the user // is "interested" in. Interest is determined by several factors (the // current focus being one of them). // // NOTE: DO NOT BLOCK WITHIN THIS CALL! // // The whole purpose of this callback is for you to acquire your slowest // of data. For this reason, you should only be sending requests to // worker threads of this callback. Then, when you are done, your data // is committed using another callback which gets invoked on the // application thread. // protected override void OnRequestSlowData(int index) { // // OnRequestSlowData can be called multiple times for the same index // if the data item is thrown away and brought back by movement in // the list by the user. For this reason, there may be a pending // picture acquire going on right now. Check if this is the case. // if (_pendingPictureAcquires.ContainsKey(index)) { return; } SlowDataResult result = new SlowDataResult(); result.Index = index; _pendingPictureAcquires[index] = result; // // Best practice: Use DeferredInvokeOnWorkerThread. // // The first param is a delegate that is called on the worker thread. // // The second param is a delegate that is called on the application thread // (after the worker thread is complete). // // Data (results) are passed between these callbacks via the third param // (the args). // Microsoft.MediaCenter.UI.Application.DeferredInvokeOnWorkerThread(AcquireSlowData, StoreSlowData, result); }