Syncronizing actions in Silverlight - c#

I have a Silverlight app that uses actions to get data from the model (which again gets the data from WCF services).
I need to somehow sync two ActionCallbacks, or wait for them, and then execute some code.
Example:
_model.GetMyTypeList(list =>
{
MyTypeList.AddRange(list);
});
_model.GetStigTypeList(list =>
{
StigTypeList.AddRange(list);
});
doSomethingWhenBothHaveReturned();
I know I can use a counter to keep track of how many has returned, but is there not a better way to do this?
EDIT: user24601 has a good answer, but CountdownEvent does not exist in silverlight, any other great ideas? :)

Yes, a counter is what you need. The 'more elegant' solution would be to use a countdown event:
using (CountDownEvent countDownEvent = new CountDownEvent(2))
{
_model.GetMyTypeList(list =>
{
MyTypeList.AddRange(list);
countDownEvent.Signal();
});
_model.GetStigTypeList(list =>
{
StigTypeList.AddRange(list);
countDownEvent.Signal();
});
countdownEvent.Wait();
doSomethingNowThatWereComplete();
}

Solved the problem my self, using a counter:
public class ActionWaitHandler
{
private int _count;
private readonly Action _callback;
public ActionWaitHandler(int count, Action callback)
{
_count = count;
_callback = callback;
}
public void Signal()
{
_count--;
if (_count == 0)
{
_callback();
}
}
}
usage:
public void method() {
var handler = new ActionWaitHandler(2, OnActionsComplete);
_model.GetMyTypeList(list =>
{
MyTypeList.AddRange(list);
handler .Signal();
});
_model.GetStigTypeList(list =>
{
StigTypeList.AddRange(list);
handler .Signal();
});
}
public void OnActionsComplete()
{
dosomething;
}

Related

WPF Event Aggregator - wait for previous execution to complete

I am working on a WPF application using Prism. I am using EventAggregator to communicate between viewmodels.
public class PublisherViewModel
{
_eventAggregator.GetEvent<RefreshEvent>().Publish("STOCKS");
}
public class SubscriberViewModel
{
public SubscriberViewModel(IEventAggregator ea)
{
ea.GetEvent<RefreshEvent>().Subscribe(RefreshData);
}
void RefreshData(string category)
{
Task.Run(() =>
{
//Long Running Operation
Dispatcher.Invoke(() =>
{
//Refresh UI
});
});
}
}
PublisherViewModel can publish event one after another. However at a SubscriberViewModel as I have a long running Task and is not awaited (which I cannot) the second request coming from publisher start execution right away. At SubscriberViewModel I want to handle all incoming request such that they are executed one after another in the order which they arrive.
I am thinking to handle this using a queue based mechanism.
Could you please suggest me the best practice for the same.
Thanks!!
Update:-
I have used the below approach
public class BlockingQueue<T> wehre T : class
{
private readonly BlockingCollection<JobQueueItem<T>> _jobs;
public BlockingQueue(int upperBound)
{
_jobs = new BlockingCollection<JobQueueItem<T>>(upperBound);
var thread = new Thread(new ThreadStart(OnStart));
thread.IsBackground = true;
thread.Start();
}
public void Enqueue(T parameter, Func<T, Task> action)
{
_jobs.Add(new JobQueueItem<T> { Parameter = parameter, JobAction = action });
}
private void OnStart()
{
foreach (var job in _jobs.GetConsumingEnumerable(CancellationToken.None))
{
if (job != null && job.JobAction != null)
{
job.Action.Invoke(job.Parameter).Wait();
}
}
}
private class JobQueueItem<T>
{
internal T Parameter { get; set; }
internal Func<T, Task> JobAction { get; set; }
}
}
public class SubscriberViewModel
{
BlockingQueue<RefreshEventArgs> RefreshQueue = new ...;
//inside Subscribed method
RefreshQueue.Enqueue(args, RefreshData);
}
Please suggest. Thanks!
I am thinking to handle this using a queue based mechanism.
This is the way to go. Set up a queue (probably an asynchronous queue), push the events in the subscriber and consume them from a worker task.
TPL Dataflow is one option to do this: create an ActionBlock<string> from the handler and post the events to it as they come in.

Throttle calls from multiple sources to a single method

I'm a bit stumped because I have a hard time finding any relevant info to my question. I'm very new to System.Reactive, so maybe I'm using it wrong.
I have a number of objects that all call a static method during an event. I want to limit the calls to that method.
public class MyObject
{
public MyObject ()
{
var observable = Observable.FromEventPattern<SizeChangedEventHandler, SizeChangedEventArgs>
(handler => SizeChanged += handler, handler => SizeChanged -= handler);
observable.Throttle (TimeSpan.FromMilliseconds (100));
observable.Subscribe (x =>
{
MethodToCall (this);
});
}
static void MethodToCall (MyObject obj)
{
// Do something.
}
}
Now, that obviously doesn't work because it only throttles calls from this single object which occur well less often than 100ms. What I think I need is some kind of static Observable that accumulates all calls and then dispatches a call after 100ms. Can anyone give me some pointers?
Update:
I implemented it with the help of a Stopwatch, which also seems to do the job. I'm still curious about a Reactive solution though.
private static Stopwatch sw = new Stopwatch();
private static void MethodToCall(MyObjectv)
{
if (sw.ElapsedMilliseconds < 100 && sw.IsRunning)
{
return;
}
// Some code here
if (sw.IsRunning)
{
sw.Restart();
}
else
{
sw.Start();
}
}
You can use the observable in the MethodToCall method implementation instead:
private static Subject<MyObject> subject = new Subject<MyObject>();
private static IDisposable subscription = subject
.Throttle (TimeSpan.FromMilliseconds (100))
.Subscribe(v =>
{
// Some code here
});
private static void MethodToCall(MyObject v)
{
subject.OnNext(v);
}
Then, the throttling becomes an internal implementation detail of MethodToCall.

Xamarin PCL - Making API calls based on user entry, how to dampen requests?

I have a search task that makes a request to an API, within a portable class library, when the user enters text in the textbox, this works as expected but I have a concern over performance at scale. When we have a large userbase all making requests to this API on every key press I can foresee performance issues.
I have limited the API call to only fire when there are more than three valid characters but I want to dampen this further. I could implement a timer over the top of this but it does not feel like a good solution and is not present in the PCL framework.
Is there a recommended pattern to achieve this type of request dampening?
private async Task GetClubs()
{
try
{
if (!string.IsNullOrWhiteSpace(ClubSearch) && ClubSearch.Replace(" ", "").Length >= 3)
{
Clubs = await dataService.GetClubs(ClubSearch);
}
}
catch (DataServiceException ex)
{
...
}
}
Usually that is done with timer. When search text changes you start (or reuse) a timer which will fire after delay and execute search request. If more text is typed during that delay - timer is reset. Sample code:
public class MyClass {
private readonly Timer _timer;
const int ThrottlePeriod = 500; // ms
public MyClass() {
_timer = new System.Threading.Timer(_ => {
ExecuteRequest();
}, null, Timeout.Infinite, Timeout.Infinite);
}
private string _searchTerm;
public string SearchTerm
{
get { return _searchTerm; }
set
{
_searchTerm = value;
ResetTimer();
}
}
private void ResetTimer() {
_timer.Change(ThrottlePeriod, Timeout.Infinite);
}
private void ExecuteRequest() {
Console.WriteLine(SearchTerm);
}
}
If timer is not available, you can do the same with Task.Delay:
public class MyClass
{
const int ThrottlePeriod = 500; // ms
private string _searchTerm;
public string SearchTerm
{
get { return _searchTerm; }
set
{
_searchTerm = value;
SearchWithDelay();
}
}
private async void SearchWithDelay() {
var before = this.SearchTerm;
await Task.Delay(ThrottlePeriod);
if (before == this.SearchTerm) {
// did not change while we were waiting
ExecuteRequest();
}
}
private void ExecuteRequest()
{
Console.WriteLine(SearchTerm);
}
}
Cheap/Fast way to implement this is a Task.Delay:
var mySearchThread = new Thread (new ThreadStart (async delegate {
while (true) {
if (!String.IsNullOrWhiteSpace(seachText) {
YourSearchMethod(seachText)
};
InvokeOnMainThread ( () => {
// Refresh your datasource on the UIthread
});
await Task.Delay (2000);
}
})).Start ();
A PCL-based solution (and amazing clean way with a great framework) is to use ReactiveUI throttling (Throttle), then you can do feats like:
// Throttle searching to every 2 seconds
this.WhenAnyValue(x => x.SearchText)
.Where(x => !String.IsNullOrWhiteSpace(x))
.Throttle(TimeSpan.FromSeconds(2))
.InvokeCommand(SearchCommand)
Ref: http://reactiveui.net
Ref: http://docs.reactiveui.net/en/user-guide/when-any/index.html

How does one kick off a timed sequence of events on the GUI thread in C#?

I've got an app that has to do the following type of things, preferably on the GUI thread since that's where most of the action is taking place and there's no long-running ops:
Wait 1000
FuncA()
Wait 2000
FuncB()
Wait 1000
FuncC()
I realize I could use a timer with a state-machine style OnTick function, but that seems cumbersome:
int _state;
void OnTick(object sender, EventArgs e) {
switch (_state) {
case 0:
FuncA();
_timer.Interval = TimeSpan.FromSeconds(2);
_state = 1;
break;
case 1:
FuncB();
_timer.Interval = TimeSpan.FromSeconds(1);
_state = 2;
break;
case 2:
FuncC();
_timer.IsEnabled = false;
_state = 0;
}
}
Plus I'd like to be able to make it generic enough to do something like
RunSequenceOnGuiThread(new Sequence {
{1000, FuncA}
{2000, FuncB}
{1000, FuncC}};
Is there an idiomatic way to do this kind of thing? Given all the TPL stuff, or Rx, or even the computation expressions in F# I'd assume one exists, but I'm not finding it.
Observable.Concat(
Observer.Timer(1000).Select(_ => Func1()),
Observer.Timer(2000).Select(_ => Func2()),
Observer.Timer(1000).Select(_ => Func3()))
.Repeat()
.Subscribe();
The only thing you have to do to make this work, is make sure that your Func's return a value (even if that value is Unit.Default, i.e. nothing)
Edit: Here's how to make a generic version:
IObservable<Unit> CreateRepeatingTimerSequence(IEnumerable<Tuple<int, Func<Unit>>> actions)
{
return Observable.Concat(
actions.Select(x =>
Observable.Timer(x.Item1).Select(_ => x.Item2())))
.Repeat();
}
Here's a sketch of this in F#:
let f() = printfn "f"
let g() = printfn "g"
let h() = printfn "h"
let ops = [
1000, f
2000, g
1000, h
]
let runOps ops =
async {
for time, op in ops do
do! Async.Sleep(time)
op()
} |> Async.StartImmediate
runOps ops
System.Console.ReadKey() |> ignore
That's in a console app, but you can just call runOps on the GUI thread. See also this blog.
If you're using VS11/NetFx45/C#5, you can do a similar thing with C# async/await and a List of Tuple of Action delegates.
using the async CTP or .NET 4.5 (C# 5) it's REALLY easy using an async method and the await operator. This can be called directly on the UI thread and it will work as expected.
public async void ExecuteStuff()
{
await TaskEx.Delay(1000);
FuncA();
await TaskEx.Delay(2000);
FuncB();
await TaskEx.Delay(1000);
FuncC();
}
Here's a way to combine "yield return" and the reactive framework to give you a "poor man's async". Basically lets you "await" any IObservable. Here I just use it for timers since that's what you were interested in, but it you can have it "await" button clicks (using a Subject<Unit>) etc before moving on to the next thing as well.
public sealed partial class Form1 : Form {
readonly Executor _executor = new Executor();
public Form1() {
InitializeComponent();
_executor.Run(CreateAsyncHandler());
}
IEnumerable<IObservable<Unit>> CreateAsyncHandler() {
while (true) {
var i = 0;
Text = (++i).ToString();
yield return WaitTimer(500);
Text = (++i).ToString();
yield return WaitTimer(500);
Text = (++i).ToString();
yield return WaitTimer(500);
Text = (++i).ToString();
}
}
IObservable<Unit> WaitTimer(double ms) {
return Observable.Timer(TimeSpan.FromMilliseconds(ms), new ControlScheduler(this)).Select(_ => Unit.Default);
}
}
public sealed class Executor {
IEnumerator<IObservable<Unit>> _observables;
IDisposable _subscription = new NullDisposable();
public void Run(IEnumerable<IObservable<Unit>> actions) {
_observables = (actions ?? new IObservable<Unit>[0]).Concat(new[] {Observable.Never<Unit>()}).GetEnumerator();
Continue();
}
void Continue() {
_subscription.Dispose();
_observables.MoveNext();
_subscription = _observables.Current.Subscribe(_ => Continue());
}
public void Stop() {
Run(null);
}
}
sealed class NullDisposable : IDisposable {
public void Dispose() {}
}
It's a slight modification of Daniel Earwicker's AsyncIOPipe idea: http://smellegantcode.wordpress.com/2008/12/05/asynchronous-sockets-with-yield-return-of-lambdas/
Interesting all the different responses. Here's a simple DIY option that doesn't depend on any other libraries, and doesn't hog thread resources unnecessarily.
Basically, for each action in your list, it creates an onTick function that executes that action, then recursively calls DoThings with the remaining actions and delays.
Here, ITimer is just a simple wrapper around DispatcherTimer (but it would work with a SWF Timer as well, or a mock timer for unit testing), and DelayedAction is just a Tuple with int Delay and Action action
public static class TimerEx {
public static void DoThings(this ITimer timer, IEnumerable<DelayedAction> actions) {
timer.DoThings(actions.GetEnumerator());
}
static void DoThings(this ITimer timer, IEnumerator<DelayedAction> actions) {
if (!actions.MoveNext())
return;
var first = actions.Current;
Action onTick = null;
onTick = () => {
timer.IsEnabled = false;
first.Action();
// ReSharper disable AccessToModifiedClosure
timer.Tick -= onTick;
// ReSharper restore AccessToModifiedClosure
onTick = null;
timer.DoThings(actions);
};
timer.Tick += onTick;
timer.Interval = first.Delay;
timer.IsEnabled = true;
}
}
If you don't want to delve into F# or reference Rx or use .Net 4.5 this is a simple viable solution.
Here's an example of how to test it:
[TestClass]
public sealed class TimerExTest {
[TestMethod]
public void Delayed_actions_should_be_scheduled_correctly() {
var timer = new MockTimer();
var i = 0;
var action = new DelayedAction(0, () => ++i);
timer.DoThings(new[] {action, action});
Assert.AreEqual(0, i);
timer.OnTick();
Assert.AreEqual(1, i);
timer.OnTick();
Assert.AreEqual(2, i);
timer.OnTick();
Assert.AreEqual(2, i);
}
}
And here's the other classes to make it compile:
public interface ITimer {
bool IsEnabled { set; }
double Interval { set; }
event Action Tick;
}
public sealed class Timer : ITimer {
readonly DispatcherTimer _timer;
public Timer() {
_timer = new DispatcherTimer();
_timer.Tick += (sender, e) => OnTick();
}
public double Interval {
set { _timer.Interval = TimeSpan.FromMilliseconds(value); }
}
public event Action Tick;
public bool IsEnabled {
set { _timer.IsEnabled = value; }
}
void OnTick() {
var handler = Tick;
if (handler != null) {
handler();
}
}
}
public sealed class MockTimer : ITimer {
public event Action Tick;
public bool IsEnabled { private get; set; }
public double Interval { set { } }
public void OnTick() {
if (IsEnabled) {
var handler = Tick;
if (handler != null) {
handler();
}
}
}
}
public sealed class DelayedAction {
readonly Action _action;
readonly int _delay;
public DelayedAction(int delay, Action action) {
_delay = delay;
_action = action;
}
public Action Action {
get { return _action; }
}
public int Delay {
get { return _delay; }
}
}
If you can use the C# 4.5 to do it, go with Firoso post: it's the best way accomplish that in C#, exactly what Async was built for.
However, if you can't, there might be some ways to do it. I'd do a "simple" manager to do it:
public partial class Form1 : Form
{
private TimedEventsManager _timedEventsManager;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_timedEventsManager
= new TimedEventsManager(this,
new TimedEvent(1000, () => textBox1.Text += "First\n"),
new TimedEvent(5000, () => textBox1.Text += "Second\n"),
new TimedEvent(2000, () => textBox1.Text += "Third\n")
);
}
private void button1_Click(object sender, EventArgs e)
{
_timedEventsManager.Start();
}
}
public class TimedEvent
{
public int Interval { get; set; }
public Action Action { get; set; }
public TimedEvent(int interval, Action func)
{
Interval = interval;
Action = func;
}
}
public class TimedEventsManager
{
private readonly Control _control;
private readonly Action _chain;
public TimedEventsManager(Control control, params TimedEvent[] timedEvents)
{
_control = control;
Action current = null;
// Create a method chain, beginning by the last and attaching it
// the previous.
for (var i = timedEvents.Length - 1; i >= 0; i--)
{
var i1 = i;
var next = current;
current = () =>
{
Thread.Sleep(timedEvents[i1].Interval);
// MUST run it on the UI thread!
_control.Invoke(new Action(() => timedEvents[i1].Action()));
if (next != null) next();
};
}
_chain = current;
}
public void Start()
{
new Thread(new ThreadStart(_chain)).Start();
}
}
Beware that this example is Winforms specific (uses Control.Invoke()). You will need a slightly different version for WPF, which uses the thread dispatcher to achieve the same thing. (if my memory doesn't fail me, you also can use Control.Dispatcher.Invoke(), but keep in mind that it is a different control)

Multithreading Errors in C#

I am trying to update a text box. I thought my threading code would fix the problem, but it does not. Can anyone help with this?
new Thread((ThreadStart)delegate { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }).Start();
Gives the following error:
Cross-thread operation not valid:
Control 'txtCapacitance' accessed from
a thread other than the thread it was
created on.
Note that all this is being started by a dataReceived function which is called whenever USB data is received.
UI objects can only be called from the UI thread. This can be accomplished via the Control's Invoke method:
txtCapacitance.Invoke((Action)(() => { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }));
You should rather have a look at using BackgroundWorker Class
Have a look at
C# BackgroundWorker Tutorial.
Updates to any UI element must be done on the UI-thread. You can certainly calculate your value on another thread, but you must use the .Invoke(...) method of the control to perform the update.
try this one
//delegate
delegate void updateTextboxDelegate(string value);
private void updateDisplay(string value)
{
txtCapacitance.Text = value;
}
//the thread
string msg = string.empty;
var th =new Thread(()=>{BeginInvoke(new updateTextboxDelegate(updateDisplay), msg); });
th.Start();
Hope that will work for you.
You need to make sure that you update textBox from same thread as you have created it.
For this purpose create yourself class helper like this and use this extensions instead of using normal way (here are couple of extensions i made for myself, but the one interesting you is changeText):
public static class ControlExtensions {
public static void changeStatus(this Control varControl, bool varState) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => changeStatus(varControl, varState)));
} else {
varControl.Enabled = varState;
}
}
public static void changeText(this Control varControl, string varText) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => changeText(varControl, varText)));
} else {
varControl.Text = varText;
}
}
public static DateTime readDateValue(this DateTimePicker varControl) {
if (varControl.InvokeRequired) {
return (DateTime) varControl.Invoke(new Func<DateTime>(() => readDateValue(varControl)));
} else {
return varControl.Value;
}
}
public static bool ReadStatus(this CheckBox varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl)));
}
return varControl.Checked;
}
public static bool ReadStatus(this RadioButton varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl)));
}
return varControl.Checked;
}
public static string readText(this Control varControl) {
if (varControl.InvokeRequired) {
return (string) varControl.Invoke(new Func<string>(() => readText(varControl)));
} else {
return varControl.Text;
}
}
public static bool readEnabled(this Control varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => readEnabled(varControl)));
} else {
return varControl.Enabled;
}
}
}
Then you use it like this: txtCapacitance.changeText("new text");

Categories

Resources