I am writing a Windows Store App toy application for Windows 8.
It has just one xaml page with a TextBlock. The page has the class MyTimer as DataContext :
this.DataContext = new MyTimer();
MyTimer implements INotifyPropertyChanged and the updating of the property Time is made with a timer:
public MyTimer(){
TimerElapsedHandler f = new TimerElapsedHandler(NotifyTimeChanged);
TimeSpan period = new TimeSpan(0, 0, 1);
ThreadPoolTimer.CreatePeriodicTimer(f, period);
}
with
private void NotifyTimeChanged(){
if (this.PropertyChanged != null){
this.PropertyChanged(this, new PropertyChangedEventArgs("Time"));
}
}
the TextBlock has a databinding on Time
<TextBlock Text="{Binding Time}" />
When I run the application i have the following exception:
System.Runtime.InteropServices.COMException was unhandled by user code
With the message
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
The real problem is that I am updating the property of the class MyTimer, not the GUI itself,
I can't figure it out, but I think the solution should use something like this one.
Yes, you're notifying property changes from a thread pool thread rather than the UI thread. You need to marshal the notification back to the UI thread in the timer callback. Now, your view model is separated from your view (a good thing) therefore it doesn't have a direct link to the Dispatcher infrastructure. So what you want to do is hand it the proper SynchronizationContext on which to communicate. To do this you need to capture the current SynchronizationContext during construction or allow it to be passed in explicitly to a constructor which is good for tests or if you're initializing the object off the UI thread to begin with.
The whole shebang would look something like this:
public class MyTimer
{
private SynchronizationContext synchronizationContext;
public MyTimer() : this(SynchronizationContext.Current)
{
}
public MyTimer(SynchronizationContext synchronizationContext)
{
if(this.synchronizationContext == null)
{
throw new ArgumentNullException("No synchronization context was specified and no default synchronization context was found.")
}
TimerElapsedHandler f = new TimerElapsedHandler(NotifyTimeChanged);
TimeSpan period = new TimeSpan(0, 0, 1);
ThreadPoolTimer.CreatePeriodicTimer(f, period);
}
private void NotifyTimeChanged()
{
if(this.PropertyChanged != null)
{
this.synchronizationContext.Post(() =>
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Time"));
});
}
}
}
One way to do this is awaiting Task.Delay() in a loop instead of using a timer:
class MyTimer : INotifyPropertyChanged
{
public MyTimer()
{
Start();
}
private async void Start()
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(1));
PropertyChanged(this, new PropertyChangedEventArgs("Time"));
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public DateTime Time { get { return DateTime.Now; } }
}
If you call the constructor on the UI thread, it will invoke the PropertyChanged there too. And the nice thing is that exactly the same code will work for example in WPF too (under .Net 4.5 and C# 5).
how about the code from this blog:
http://metrowindows8.blogspot.in/2011/10/metro-tiles.html
This worked for me.
I had to pass a ThreadPoolTimer object to my delegate function
Related
I'm having an issue with updating WPF UI with the RX. Currently I have a class that has an event which is called within its functions. Event is subscribed from the UI thread and updates the UI like below :
SomeClass.cs
public partial class SomeClass
{
public delegate Task ProgressUpdate(string value);
public delegate Task BarUpdate(int value);
public event ProgressUpdate OnProgressUpdateList;
public event BarUpdate OnProgressUpdateBar;
public async Task DoSomething()
{
// execute code
<some code>
// update UI
if (OnProgressUpdateList != null)
{
OnProgressUpdateList(update);
}
}
}
And in MainWindow.xaml
var someClass = new SomeClass();
someClass.OnProgressUpdateList += Export_OnProgressUpdateList;
someClass.OnProgressUpdateBar += Export_OnProgressUpdateBar;
private async Task Export_OnProgressUpdateList(string text)
{
await Dispatcher.InvokeAsync(() =>
{
OutputLog.AppendText(text);
OutputLog.AppendText(Environment.NewLine);
OutputLog.ScrollToEnd();
});
}
This code works except the program processes huge number of files and I'm assuming this is why the UI becomes frozen very quickly (I see the updates being done in the first half a second). I searched for a way around this and I came into a solution to use RX for batching the UI calls. I've searched through several SO posts but I couldn't find an answer on how to correctly implements this (or convert C# events to RX observables) when I call those events from the class and subscribe to this event from outside that class. Can someone help me understand this?
I'm posting an answer to myself as I couldn't get one here and I finally figured it out so for anyone looking for that in the future - here you go:
public partial class SomeClass {
public Subject<string> outputLogSubject = new Subject<string>();
public IObservable<string> OutputLog => outputLogSubject.AsObservable();
//Add string for collection updating UI
outputLogSubject.OnNext(string);
//After finishing the work you can call outputLogSubject.OnCompleted() to stop buffering
outputLogSubject.OnCompleted();
}
It needs to be added in the class that will be calling the executing the work.
Below needs to be added in the UI thread after initialization and BEFORE processing work :
var buffer = someClass.OutputLog.Buffer(TimeSpan.FromMilliseconds(1000), 6);
var chunked = buffer.ObserveOnDispatcher(DispatcherPriority.Background);
var update = chunked.Subscribe(name =>
{
foreach (var item in name)
{
OutputLog.AppendText(item);
}
OutputLog.ScrollToEnd();
});
This allowed me to keep the UI responsive to the point of seeing the output log is real time
I have a class with properties that are bound to my view. To keep my view up-to-date, I implement INotifyPropertyChanged and raise the event everytime some property changes.
Now I got some heavy functions that freeze my application. I want to put them into a background task.
First: here my current approach
(e.g. on button click)
private async void HeavyFunc()
{
foreach (var stuff)
{
count += await Task.Run(() => stuff.Fetch());
}
if (count == 0)
//...
}
stuff class
public async Task<int> Fetch()
{
//network stuff
RaisePropertyChanged("MyProperty");
}
public async void RaisePropertyChanged(string pChangedProperty)
{
await Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new ThreadStart(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty);
}
);
}
The code above gives an exception ("DependencySource" must be created in the same thread like "DependencyObject").
AFAIK, you generally need to create a new thread and run it (while awaiting it). ´await Task.Run(...);´ should do this job.
Since the PropertyChanged event directly influences the UI, calling it in the UI thread seems to be a good decision. This is why I call Dispatcher.BeginInvoke.
What I don't understand: the exception above is caused when different threads are responsible for the data. But I explicitely calling the event on my UI-thread and the object should be created by the UI-thread too. So why do I get an exception?
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above? What should be considered while constructing the functions?
Now I got some heavy functions that freeze my application.
If you're really doing asynchronous "network stuff", then it shouldn't be freezing the app.
My main question is: How do I implement the events for the INotifyPropertyChanged interface generally to avoid or handle most of the async programming problems like above?
The approach that I prefer is to not handle this in the event raising code. Instead, structure the rest of your code so that it respects the UI layer.
In other words, divide your "service" (or "business logic") code from your "UI" code so that it works like this:
// In StuffService class:
public async Task<Result> FetchAsync()
{
//network stuff
return result;
}
// In StuffViewModel class:
public async void ButtonClicked()
{
foreach (var stuff)
{
var result = await Task.Run(() => _stuffService.FetchAsync());
MyProperty = result.MyProperty;
count += result.Count;
}
if (count == 0)
//...
}
public Property MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string pChangedProperty = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pChangedProperty));
}
This way, there's no manual thread jumping, all properties have the standard ViewModel implementation, the code is simpler and more maintainable, etc.
I did leave in the call to Task.Run, although this should be superfluous if your network calls are truly asynchronous.
I am working on a WPF GUI (using MVVM) to control an embedded device. As of yet, the device is still in development and not currently functioning reliably. As such I have created the following fake device:
interface IConnection
{
bool IsValid { get; }
bool Open();
void Close();
void Write(string message);
}
class SerialConnection : IConnection
{
// Not yet implemented
}
class DevConnection : IConnection
{
Timer _timer;
Action<string> _callback;
public bool IsValid {...}
public DevConnection(Action<string> callback)
{
_timer = new Timer(tick, null, Timeout.Infinite, Timeout.Infinite);
_callback = callback;
}
public bool Open() {...}
public void Close() {...}
public void Write(string Message) {...}
private void tick(object args)
{
_callback("V01" + ToHex(vol1) + "\n");
...
}
}
The
Action<string> _callback;
is the function used by my model to read the payload of the connection and update its state appropriately
class Model
{
IConnection _connection;
public Model()
{
_connection = new DevConnection(Message);
}
private void Message(string payload)
{
...
_volume1 = floatValue;
...
}
}
However when the Model is created, I change a bunch of the properties elsewhere before calling Model.IConnection.Open() to start the timer. Every time the Message() callback is called, the debugger shows the Model as still being in its original, constructed state.
1) What is going on behind the scenes here? Is the Threading.Timer creating a new thread for its counting / tick execution? If so, why is it creating a default copy of my Model class?
2) How do I fix it? I even tried giving the DevConnection a copy of my Model class to operate on directly (not how I'd like to setup the architecture) and it still resulted in the same undesired behavior
Unfortunately I have only a rudimentary understanding of the theory of threading, with no idea how to implement it in C#. Tragically I suspect that this issue is a result of thread mis-management.
Given that the mysterious "extra copies of the Model class" issue was solved. There remains the issue of how you can safely update your UI from a timer scheduled callback.
As was mentioned by #Frank J, your callback will be invoked on a thread pool thread, whereas it is only allowed to update UI elements from the context of the UI thread. This means you will need to marshal the callback's actions performed in the Message method to the UI thread context if they directly or indirectly update UI elements.
The code snippet below shows one way of doing that.
class Model
{
private readonly SynchronizationContext _synchronizationContext;
private readonly IConnection _connection;
public Model()
{
// Capture UI synchronization context.
// Note: this assumes that Model is constructed on the UI thread.
_synchronizationContext = SynchronizationContext.Current;
_connection = new DevConnection(MessageCallback);
}
private void MessageCallback(string payload)
{
// schedule UI update on the UI thread.
_synchronizationContext.Post(
new SendOrPostCallback(ctx => Message(payload)),
null);
}
private void Message(string payload)
{
...
_volume1 = floatValue;
...
}
}
One more piece of advice: I think IConnection should be an IDisposable because you will have to dispose of the timer somewhere.
I've been writing an API that facilitates communication with a serial port. I'm doing some refactoring and general cleanup and was wondering if there's a way to avoid the following issue.
The main class in the API has the capability to constantly read from the port and raise an event containing a value when the read bytes match a particular regex. The process of reading and parsing occurs on another thread. The event contains the value as an argument (string) and because it's being raised from another thread, a client attempting to directly assign the value to, say, the Text property of a control causes a cross-thread exception unless the handler has the proper Invoke code.
I understand why this happens, and when I put the proper invocation code in my test client's event handler, all is well; my question is whether or not there's anything I can do in the API code itself such that clients don't have to worry about it.
Essentially, I'd like to turn this:
void PortAdapter_ValueChanged(Command command, string value)
{
if (this.InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
receivedTextBox.Text = value;
}));
}
else
{
receivedTextBox.Text = value;
}
}
into simply this:
void PortAdapter_ValueChanged(Command command, string value)
{
receivedTextBox.Text = value;
}
Well there is a common pattern for that used many places in .Net framework itself. For example BackgroundWorker uses this model.
For that you'll take a SynchronizationContext as a parameter for your API, in this case I assume it is PortAdapter.
When raising an event, you raise the event in given SynchronizationContext using SynchronizationContext.Post or SynchronizationContext.Send. Former is asynchronous and latter is synchronous.
So, when client code creating a instance of your PortAdapter, it passes WindowsFormsSynchronizationContext instance as parameter. Which means that PortAdapter will raise the event in given synchronization context and that also means that you don't need a InvokeRequired or Invoke calls.
public class PortAdapter
{
public event EventHandler SomethingHappened;
private readonly SynchronizationContext context;
public PortAdapter(SynchronizationContext context)
{
this.context = context ?? new SynchronizationContext();//If no context use thread pool
}
private void DoSomethingInteresting()
{
//Do something
EventHandler handler = SomethingHappened;
if (handler != null)
{
//Raise the event in client's context so that client doesn't needs Invoke
context.Post(x => handler(this, EventArgs.Empty), null);
}
}
}
Client code:
PortAdapter adpater = new PortAdapter(SynchronizationContext.Current);
...
It is very important to create instance of PortAdapter in UI thread, otherwise SynchronizationContext.Current will be null and hence events will be still raised in ThreadPool thread.
More about SynchronizationContext here.
TBH, the approach with checking for InvokeRequired is fine and flexible.
But if you like, you can have all events in your application UI-safe. For this either all classes have to have invocation control registered
public class SomeClassWithEvent
{
private static Control _invoke = null;
public static void SetInvoke(Control control)
{
_invoke = control;
}
public event Action SomeEvent;
public OnSomeEvent()
{
// this event will be invoked in UI thread
if (_invoke != null && _invoke.IsHandleCreated && SomeEvent != null)
_invoke.BeginInvoke(SomeEvent);
}
}
// somewhere you have to register
SomeClassWithEvent.SetInvoke(mainWindow);
// and mayhaps unregister
SomeClassWithEvent.SetInvoke(null);
or have that invocation control exposed, to example:
// application class
public static class App
{
// will be set by main window and will be used even risers to invoke event
public static MainWindow {get; set;}
}
You will have difficulties if event occur when no handle is created or control registered.
You can trigger the event in the UI Thread, this way the event handler (if any) will already be in the UI thread.
public class PortAdapter
{
public event EventHandler<string> ValueChanged;
protected virtual void OnValueChanged(string e)
{
var handler = ValueChanged;
if (handler != null)
{
RunInUiThread(() => handler(this, e));
}
}
private void RunInUiThread(Action action)
{
if (InvokeRequired)
{
Invoke(action);
}
else
{
action.Invoke();
}
}
}
However this is not good design because you don't know if an handler will perform UI interaction.
This is probably a really basic question, please bear with me, I'm still very new to the world of WPF/C#.
I have a WPF app where I open a new window if a button is clicked.
The window is called Sync and all it does is instantiate a viewmodel class which contains some public properties that are bound to my view.
The viewmodel also instantiates a class containing a lot of business logic, this updates the ViewModel's bound properties, the aim being to update the content of my window.
This sort of works, but only when all of the (sometimes quite lengthy) processing is completed does the window load and the view is populated with the last value of the ViewModel's properties.
I think I'm missing something pretty basic here. How do I get my window to instantly load and then have the view update when any of the properties have changed? Should I be listening for a PropertyChanged event and then updating the view? Where do i do this? Within the view model's setter?
Here's some simplified code:
Calling my window from my main window's View Model
public void SyncAction()
{
Sync syncWindow = new Sync();
syncWindow.Show();
syncWindow.Activate();
}
The window
public partial class Sync : Window
{
public Sync()
{
InitializeComponent();
var viewModel = new SyncViewModel();
}
}
The view model
class SyncViewModel
{
private string _miscStatus = "";
public SyncViewModel()
{
var sync = new SyncLogic();
sync.SyncAll(this);
}
public string MiscStatus
{
get
{
return _miscStatus;
}
set
{
_miscStatus += value;
}
}
}
Some business logic
class SyncLogic
{
private ViewModel.SyncViewModel _syncViewModel;
public void SyncAll(ViewModel.SyncViewModel syncViewModel)
{
_syncViewModel = syncViewModel;
// lock our synctime
var syncTime = DateTools.getNow();
_syncViewModel.MiscStatus = "Sync starting at " + syncTime.ToString();
// Do lots of other stuff
_syncViewModel.MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
}
Bonus question: The way I'm updating the view from within my business logic (by passing in a reference to the viewmodel and updating its properties from there) seems a bit kludgy. I definitely want to keep the business logic separate, but am not sure how I can pass any output back out to the viewmodel. What would be a better way of doing this please?
Why do you care whether the update takes visual effect before or after the code finishes executing? The internal properties are updated immediately; any code that queries the UI will see the new values.
The only time the user will be able to perceive a difference between an update during execution vs after execution is if you have a long-running computation on the UI thread. Don't do that.
Instead, run the computation asynchronously with the UI, so that repaint messages can be processed meanwhile. You can do this using a background thread, but the new easier way with C# 4 and later is async. Because async is implemented using continuation messages to the UI thread, you don't need to synchronize data access or marshal UI access between threads. It just works, and very well. The only thing you need to do is to break your code into small enough chunks, each implemented as an async method, that you don't cause noticeable delay.
What I would do:
Don't do any heavy logic in the ViewModel constructor. Constructor should only initialize object and do nothing else. In your example, constructor should be empty.
public SyncViewModel()
{
}
SyncLogic should not be aware of the ViewModel. Introduce some other class to communicate input arguments and sync results. Let's say SyncArguments and SyncResult.
class SyncLogic
{
public SyncResult SyncAll(SyncArguments syncArgs)
{
var syncResult = new SyncResult();
// Do lots of other stuff
// populate syncResult
return syncResult;
}
}
Introduce a method in the viewmodel that should be called to do the "sync" logic, and make that method async. That way it's very easy to do the heavy stuff in the background and leave the UI thread to do the job it should do, draw the UI.
public async Task Sync()
{
// lock our synctime
var syncTime = DateTools.getNow();
MiscStatus = "Sync starting at " + syncTime.ToString();
var sync = new SyncLogic();
var syncArgs = new SyncArguments();
//populate syncArgs from ViewModel data
//call the SyncAll as new Task so it will be executed as background operation
//and "await" the result
var syncResults = await Task.Factory.StartNew(()=>sync.SyncAll(syncArgs));
//when the Task completes your execution will continue here and you can populate the
//ViewModel with results
MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
Make the button click event handler that creates and shows the window async, so you can call Sync method on the ViewModel
private void async Button_click(object sender, EventArgs e)
{
Sync syncWindow = new Sync();
var viewModel = new SyncViewModel();
syncWindow.DataContext = viewModel;
syncWindow.Show();
syncWindow.Activate();
await viewModel.Sync();
}
That will draw the Window without waiting on the Sync method. When the Sync taks completes, viewmodel properties will be populated from the SyncResult and the Bindings will draw them on screen.
Hope you get the idea, sorry if there are some errors in my code, not sure that it all compiles.
First, make sure to set the viewmodel as the view's DataContext:
public partial class Sync : Window
{
public Sync()
{
InitializeComponent();
var viewModel = new SyncViewModel();
DataContext = viewModel;
}
}
Second, you'll have to run the "sync" stuff on a background thread. This is easiest with the async+await keywords in .Net 4.5:
public async void SyncAll(ViewModel.SyncViewModel syncViewModel)
{
_syncViewModel = syncViewModel;
// lock our synctime
var syncTime = DateTools.getNow();
_syncViewModel.MiscStatus = "Sync starting at " + syncTime.ToString();
await Task.Factory.StartNew(() => {
// Do lots of other stuff
});
_syncViewModel.MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
With databinding your Window will automatically updated as long as it notified that properties it bound to has been changed. So what you need is implement INotifyPropertyChanged in the viewmodel and raise property changed event whenever binding source property value changed. For example:
public class SyncViewModel : INotifyPropertyChanged
{
private string _miscStatus = "";
public string MiscStatus
{
get{ return _miscStatus; }
set
{
_miscStatus += value;
OnPropertyChanged("MiscStatus");
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
In case somebody else comes across this issue in WPF, the solution described here is really simple and just worked fine for me. It uses an extension method to force an UIElement to be rendered:
public static class ExtensionMethods
{
private static Action EmptyDelegate = delegate() { };
public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
}
}
Then, simply use as:
private void SomeLongOperation()
{
// long operations...
// UI update
label1.Content = someValue;
label1.Refresh();
// continue long operations
}
}
Quoting the original author:
The Refresh method is the extension method that takes any UI element and then calls that UIElement's Dispatcher's Invoke method. The trick is to call the Invoke method with DispatcherPriority of Render or lower. Since we don't want to do anything, I created an empty delegate. So how come this achieves refresh functionality?
When the DispatcherPriority is set to Render (or lower), the code will then execute all operations that are of that priority or higher. In the example, the code already sets label1.Content to something else, which will result in a render operation. So by calling Dispatcher.Invoke, the code essentially asks the system to execute all operations that are Render or higher priority, thus the control will then render itself (drawing the new content). Afterwards, it will then execute the provided delegate (which is our empty method).