0

How to set System.Timers.Timer in presenter in order to elapse in view thread?

Environment: C#, .NET 4.0 CP, WinForms

My current cod is here, but it doesn't work. I have to additionally "Invoke" in the view.

I cast view to ISynchronizeInvoke to build the code. Casting to Control doesn't help.

public class GeneratorPagePresenter : IGeneratorPagePresenter
{
    private IGeneratorPage view;
    private Timer timer;

    public void SetView(IGeneratorPage generatorPage)
    {
        view = generatorPage;

        timer = new Timer();
        timer.Interval = 1000;
        timer.AutoReset = true;
        timer.SynchronizingObject = (ISynchronizeInvoke) view;
        timer.Elapsed += Timer_Elapsed;
    }

    void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        view.UpdateProgress(percentage);
    }
}

EDIT

Thanks to AnPasant comment (which mysteriously disapeared). I set SynchronizingObject as a parameter. It works fine, but the code looks something strange.

    public void SetView(IGeneratorPage generatorPage, ISynchronizeInvoke sync)
    {
        view = generatorPage;

        timer = new Timer();
        timer.Interval = 1000;
        timer.AutoReset = true;
        timer.SynchronizingObject = sync;
        timer.Elapsed += Timer_Elapsed;
    }

This method is called by View as follows:

        presenter.SetView(this, this);
Miroslav Popov
  • 3,294
  • 4
  • 32
  • 55

1 Answers1

0

The thing is that you have to switch Synchronization Context somewhere. ViewModel in this case schould be created in UI Thread.

private IGeneratorPage view;
private Timer timer;
private SynchronizationContext uiSyncContext;

public GeneratorPagePresenter()
{
    uiSyncContext = SynchronizationContext.Current;
}

public void SetView(IGeneratorPage generatorPage)
{
    view = generatorPage;

    timer = new Timer();
    timer.Interval = 1000;
    timer.AutoReset = true;
    timer.Elapsed += Timer_Elapsed;
}

void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    uiSyncContext.Post((state) => view.UpdateProgress(percentage), null);                
}
Vladimir Gondarev
  • 1,243
  • 7
  • 14
  • This code also rises Exception "Cross-thread operation not valid..." View and Presenter are created by UnityContainer. – Miroslav Popov Oct 28 '13 at 21:36
  • If SynchronizationContext.Current is not set, it throws an exception. check this thread: http://stackoverflow.com/questions/9377290/synchronizationcontext-current-is-null-on-resolving-with-unity-in-wpf – Vladimir Gondarev Oct 29 '13 at 20:00