English 中文(简体)
在使用TPL时,我如何在ID 深处援引一种方法?
原标题:How do I invoke a method on the UI thread when using the TPL?
  • 时间:2011-09-06 17:59:10
  •  标签:
  • mvvm

我正在使用TPL进行多功能手术。 任务需要向调查组报告进展情况,以便更新进展诊断。 由于该表是MVVM,进步方言必须服从于一种名为“进步”的观念模型,该模型以带有签名<编码>的最新进度表的视角模型加以更新。 背景任务需要将这种方法称为报告进展情况。

我使用一种方法更新财产,因为它让每一项任务以不同数额增加进步财产。 因此,如果我有两个任务,第一个任务需要四倍的时间,第一个任务叫<代码>UpdateProgress(4)/code>,第二个任务叫UpdateProgress(1)。 因此,第一个任务完成时进展率为80%,第二个任务完成时进展为100%。

My question is really pretty simple: How do I call the view model method from my background tasks? Code is below. Thanks for your help.


任务使用<代码>Parallel。 每种(,在编码中,照此办理:

private void ResequenceFiles(IEnumerable<string> fileList, ProgressDialogViewModel viewModel)
{
    // Wrap token source in a Parallel Options object
    var loopOptions = new ParallelOptions();
    loopOptions.CancellationToken = viewModel.TokenSource.Token;

    // Process images in parallel
    try
    {
        Parallel.ForEach(fileList, loopOptions, sourcePath =>
        {
            var fileName = Path.GetFileName(sourcePath);
            if (fileName == null) throw new ArgumentException("File list contains a bad file path.");
            var destPath = Path.Combine(m_ViewModel.DestFolder, fileName);
            SetImageTimeAttributes(sourcePath, destPath);

            // This statement isn t working
            viewModel.IncrementProgressCounter(1);
        });
    }
    catch (OperationCanceledException)
    {
        viewModel.ProgressMessage = "Image processing cancelled.";
    }
}

The statement viewModel.Increment ProgramressCounter(1) isn thanging an special, but it not take to the main thread. 任务从MVVERSICommand的物体中删除,其编号为:

public void Execute(object parameter)
{
    ...

    // Background Task #2: Resequence files
    var secondTask = firstTask.ContinueWith(t => this.ResequenceFiles(fileList, progressDialogViewModel));

    ...
}
最佳回答

穿甲型肝炎法,可使用异构体异构体。 如果你使用卡拉伊伯恩等多国公司框架,则会对派遣者进行抽象的解读,以便你能够使用外阴做几乎相同的事情。 OnUIThread(Action).

微软关于如何使用发送器的文章。

问题回答

假设你的看法是 constructed(即:根据观点,或针对与观点相关的事件)构造的,几乎总是海事组织,你可以把这一点添加到你建造者身上:

// Add to class:
TaskFactory uiFactory;

public MyViewModel()
{
    // Construct a TaskFactory that uses the UI thread s context
    uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}

接着,当你获得活动时,你可以利用这一机会来挽救:

void Something()
{
    uiFactory.StartNew( () => DoSomething() );
}

Edit: I made an util class. It is static but if you want you can create an interface for it and make it nonstatic:

public static class UiDispatcher
{
    private static SynchronizationContext UiContext { get; set; }

    /// <summary>
    /// This method should be called once on the UI thread to ensure that
    /// the <see cref="UiContext" /> property is initialized.
    /// <para>In a Silverlight application, call this method in the
    /// Application_Startup event handler, after the MainPage is constructed.</para>
    /// <para>In WPF, call this method on the static App() constructor.</para>
    /// </summary>
    public static void Initialize()
    {
        if (UiContext == null)
        {
            UiContext = SynchronizationContext.Current;
        }
    }

    /// <summary>
    /// Invokes an action asynchronously on the UI thread.
    /// </summary>
    /// <param name="action">The action that must be executed.</param>
    public static void InvokeAsync(Action action)
    {
        CheckInitialization();

        UiContext.Post(x => action(), null);
    }

    /// <summary>
    /// Executes an action on the UI thread. If this method is called
    /// from the UI thread, the action is executed immendiately. If the
    /// method is called from another thread, the action will be enqueued
    /// on the UI thread s dispatcher and executed asynchronously.
    /// <para>For additional operations on the UI thread, you can get a
    /// reference to the UI thread s context thanks to the property
    /// <see cref="UiContext" /></para>.
    /// </summary>
    /// <param name="action">The action that will be executed on the UI
    /// thread.</param>
    public static void Invoke(Action action)
    {
        CheckInitialization();

        if (UiContext == SynchronizationContext.Current)
        {
            action();
        }
        else
        {
            InvokeAsync(action);
        }
    }

    private static void CheckInitialization()
    {
        if (UiContext == null) throw new InvalidOperationException("UiDispatcher is not initialized. Invoke Initialize() first.");
    }
}

使用:

void Something()
{
    UiDispatcher.Invoke( () => DoSomething() );
}




相关问题
Reactive Extensions (Rx) + MVVM =?

One of the main examples being used to explain the power of Reactive Extensions (Rx) is combining existing mouse events into a new event representing deltas during mouse drag: var mouseMoves = from ...

Where should the data be stored in MVVM?

I ve got this Silverlight Prism application that is using MVVM. The model calls a WCF service and a list of data is returned. The ViewModel is bound to the View, so the ViewModel should have a List ...

Where to put the calls to WCF or other webservices in MVVM?

I m building Silverlight applicaitions using Prism and MVVM. When calling WCF services on your own server, or even external webservices like the Bing api, would this be done from the Model? or from ...

How to avoid View specific code in my ViewModel

My application has a menu option to allow the creation of a new account. The menu option s command is bound to a command (NewAccountCommand) in my ViewModel. When the user clicks the option to create ...

WPF MVVM User Control binding issues

I have an application that uses MVVM. I have several items on the main window that bind to the ViewModel for that window. When I run it everything works. However, when I add a user control to the main ...

WPF: writing smoke tests using ViewModels

I am considering to write smoke tests for our WPF application. The question that I am faced is: should we use UI automation( or some other technology that creates a UI script), or is it good enough to ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

热门标签