Monotouch - Getting notified when network status changed - xamarin.ios

I'm familiar with the "reachability" class to check if there is an internet connection:
https://github.com/xamarin/monotouch-samples/blob/master/ReachabilitySample/reachability.cs
I was now wondering if there is any way to get notified when the Network status has changed?
Let's say that my collection is loaded when there is no internet. The images will not get loaded. I would like to trigger the download again if the iPad suddenly gets internet connection again.
In the reachability class, I see following code:
public static event EventHandler ReachabilityChanged;
static void OnChange (NetworkReachabilityFlags flags)
{
var h = ReachabilityChanged;
if (h != null)
h (null, EventArgs.Empty);
}
However, if I set a breakpoint in the "OnChange" method, it's not called when I switch off Wifi.
Any ideas?
Regards, Matt

Ok, I should have find the answer myself actually.
You should call following functions first before you will be notified:
Reachability.InternetConnectionStatus ();
Reachability.LocalWifiConnectionStatus ();
Reachability.RemoteHostStatus ();
Calling these 3 static function calls will initialize all the necessary objects. Those 3 objects will get notified when there is a change and call "OnChange" in the Reachability call (which notifies your Event Handler).
(off course, even better is to create a special function which initialize all the needed objects so you don't need to call these 3 functions as they will really test the network connection already)

You should be able to simply add an event handler to the ReachabilityChanged event, something like (the not test compiled);
Reachability.ReachabilityChanged += c_ReachabilityChanged;
static void c_ReachabilityChanged(object sender, EventArgs e)
{
Console.WriteLine("Here I can handle that network reachability changed.");
}

Just calling this would work, can be written in AppDelegate
Reachability.RemoteHostStatus ();
Reachability.ReachabilityChanged += ReachabilityChanged;
static void ReachabilityChanged(object sender, EventArgs e){//Do Something};

Related

Displaying countdown in multi threaded C# WIndows Forms app

I have tried several solutions with timers (tried all three timer classes) and none fire the Tick(elapsed) event in that specific spot. I have a multi-threaded WinForms application.
What I need seems simple but I have spent days on this and ready to throw in the towel.
I need to display the live countdown in a pop up by second while an action is being executed. If 90 seconds pass with no results achieved (i have a flag), display warning, so I need to update the UI thread for sure.
I have looked into three different Timer classes and none work for me in that particular spot - their elapsed or tick events do not fire. I am thinking it's because I already have another thread that's polling the Serial Port because if I create a dummy button and tie the timer to the Click event, it's fine. Please note that I don't need the Timer to start inside the Serial Port polling, the functionality is totally separate.
Can someone suggest any solution that might work in this case?
Classes i tried are
Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
This answer assumes the "Popup" will not blocking the main UI Thread.
Create new MIDI child Form for your "Popup" if you want it to exist within the confines of the parent form otherwise this works fine.
Code taken from Alex's very helpful answer here: How to use a BackgroundWorker?
public Popup()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if(progressBar1.Value == 90)
WarningLbl.Text = "WARNING: Process is taking too long to complete.";
}

IrrKlang Sound Library and Stop Event threads

I have a question about using external c++ library (irrKlang.dll) which is an audio playback engine. Now, the problem is that when I get a SoundStopped event out of it, and do an action in the main form, all kinds of stack related errors arise. Let me show the code:
namespace WindowsFormsApplication4
{
public class IsoundFinished : ISoundStopEventReceiver
{
public delegate void OnSoundStoppedEventHandler(object source, EventArgs e);
public event OnSoundStoppedEventHandler IStopped;
public void OnSoundStopped(ISound iSound, StopEventCause reason, object userData)
{
if (reason.ToString() == "SoundFinishedPlaying")
IStopped?.Invoke(this, EventArgs.Empty);
}
}
}
That is an extended class for me to do custom actions (for example - if sound finished, raise the event...) I am creating an instance of it, for the event action to get exposed in my main Form1 class:
IsoundFinished iStopReceiver = new IsoundFinished();
Now in my main form, I have this line in my Form1() method, just under my InitializeComponent():
iStopReceiver.IStopped += new soundFinished.OnSoundStoppedEventHandler(OnStopped);
It's for subscribing to the event handler. And finally - my OnStopped() method which is supposed to do stuff when the song ends it's playback - it's on the same Form1:
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}
My Stop1 button method is (for those who work with the IrrKlang) ISound.Stop(); and few more lines of code, dealing with the display of playlist and so on. Although I have invoked it from the main UI thread - which should provide me with some degree of thread misalignment protection, all kinds of errors appear, mostly
Cannot evaluate expression because a native frame is on the top of the call stack.
Of course, if I do it without event handler, ISound.Stop(); drops the sound from the engine, like it should. I know something wrong is happening with the threads, but I can't figure out what's going on. If someone would give me few tips, I'd appreciate that a lot.
Well it seems I've solved it myself ! It's all about understanding how the threads are working in Visual C#. The problem was this : I was actually PAUSING the background thread where my audioengine was triggering the event - so 'till I performed an action after INVOKE in the main UI thread, background thread was paused along with the whole irrKlang engine. It was unable to purge itself properly, so it's call stack got clogged!
Using BEGININVOKE solved the problem, as it doesn't PAUSE the background task. It lets it run instead. Diagram on this answer gave me much needed piece of info I was looking for.
Maybe someone will need this answer too, glad I helped myself :P
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}

Multithreading - how to invoke Action

I have some menu popup with action buttons. This is popup so it is made in new thread. I add event to created buttons something like this:
private StdProcedure m_ToInvoke;
public void AddButton()
{
Button myChildTempButton = new Button();
myChildTempButton.ItemClick += new ItemClickEventHandler((x, y) =>
{
HidePopup(); m_ToInvoke = myOpp.Procedure;
});
}
StdProcedure is delegate
public delegate void StdProcedure();
And after close event:
protected override void OnPopupClosed()
{
base.OnPopupClosed();
if (m_ToInvoke != null) m_ToInvoke.Invoke();
}
That doesn't work correctly. Sometime invoked operations stopped my another thread and I don't understand how it's works.
My question is what is the different between:
m_ToInvoke()
m_ToInvoke.Invoke()
m_ToInvoke.BeginInvoke()
m_ToInvoke.DynamicInvoke()
and what should I use here?
For me first and second is the same in effect.
m_ToInvoke() is just C# syntactic sugar for m_ToInvoke.Invoke()
m_ToInvoke.Invoke() executes the delegate synchronously, in the same thread
m_ToInvoke.BeginInvoke() schedules the delegate for invocation in a thread-pool thread; the returned IAsyncResult can be used to wait for it to complete, and you can also pass in a callback
m_ToInvoke.DynamicInvoke() is the only one of these methods to be declared by Delegate - it's similar to calling it by reflection, in that there's no compile-time safety for the number/type of the arguments etc.
Note that calling Invoke/BeginInvoke on a delegate is very different to calling Dispatcher.Invoke/BeginInvoke or Control.Invoke/BeginInvoke, which are to do with invoking a delegate within the UI thread for a WPF/WinForms app - although again, the Invoke version is synchronous and BeginInvoke is asynchronous.

Accessing UI from non-ui thread using dispatcher did not work

I am beginner to C# .net. I have simple app in wpf which access a listbox from user thread. in winforms i can use invokerequired, a equivalent for wpf using dispatcher did not help. My system also hangs for the buttons so debugging is though. Please provide solution for the below code. thanks in advance
private void Monitor_mtd()
{
while (AppStatus != 0)
{
if (flag2 == 1)
{
listBox1.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new list1MtdDelegate(list1Mtd), "Best practice");
}
}
}
private delegate void list1MtdDelegate(string ls1);
private void list1Mtd(string ls1)
{
listBox1.Items.Add(ls1);
}
private void button1_Click_1(object sender, RoutedEventArgs e)
{
Monitor = new Thread(new ThreadStart(Monitor_mtd));
Monitor.Start();
flag1 = 1;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
flag2 = 1;
}
There are a couple of issues that arise in your approach. Firstly, the way that you bind your data to the ListBox and secondly trying to update the ListBox from a user thread.
You can solve the binding of the ListBox by using an ObservableCollection so that the UI is updated with the necessary values (have a look at this post for more information on this). However, this also raises another problem and that is that the ObservableCollection cannot be called from another thread other than the one it is dispatching (see more on this here also). This means that you need another implementation for the ObservableCollection. Thomas Levesque made an AsyncObservableCollection that can be modified from any thread and still notify the UI when its modified.
I made a sample implementation that you can download here showing the full solution.

DNN 5 - Can't get current ModuleId from nested user control in custom module

I'm writing a custom module for DNN 5, and I need a "Manage" link to be on every control in the module. I created a new UserControl ("ManagerLink") that inherits from PortalModuleBase, put my link into that control, and dropped that control on ALL OF MY MAIN CONTROLS.
The problem is that ModuleId and TabId are always -1 in "ManagerLink" nested control. PortalId works just fine, and I can get a TabId by doing PortalSettings.ActiveTab.TabID.
Why can't I get ModuleId and TabId in from "ManagerLink" control, even though it inherits from PortalModuleBase?
Is there an alternative method to get ModuleId (equivalent of PortalSettings.ActiveTab.TabID)
UPDATE 2014:
Just saw another answer that's way better than the original (and accepted it).
If you're using DNN 6 and earlier, replace ModuleBase with PortalModuleBase
William Severance from DNN forum answered this one for me, I'll post the answer here as well.
Since the child control inherits from PortalModuleBase, I would do the
following in the Page_Load handler of
the parent control
Note: ManagerLink is assumed to be a reference to the child control
VB.NET:
With ManagerLink
.ModuleConfiguration = Me.ModuleConfiguration
.LocalResourceFile = Me.LocalResourceFile
End With
C#:
protected void Page_Load(System.Object sender, System.EventArgs e)
{
ManagerLink.ModuleConfiguration = this.ModuleConfiguration;
ManagerLink.LocalResourceFile = this.LocalResourceFile
}
The above allows the child control to use the parent's ModuleConfiguration (which will include ModuleId) and LocalResourceFile for any localization.
I just wanted to add my 2 cents here, using the answer of #roman-m and extending on it,
I was able to do it in the nested control itself like so:
//fires first in the sequence, calling initialise components
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
//this binds a handler to the parent's init event
this.Parent.Init += new EventHandler(this.Parent_Init);
}
//the handler gets called, at this point we can cast the parent as a module base
//and load the configuration and resource file into the nested control
private void Parent_Init(object sender, System.EventArgs e)
{
this.ModuleConfiguration = ((ModuleBase)this.Parent).ModuleConfiguration;
this.LocalResourceFile = ((ModuleBase)this.Parent).LocalResourceFile;
}
This means that in the Page_Load event of the nested control it will already have the configuration and local resource file on hand.
It also means you don't have to load the configuration and local resource file in on every parent control which uses the child control.
This will only work when the parent is of type ModuleBase of course
And to be even more specific, this works in version 7.00.06

Resources