How can I use SaveContactTask without exiting program in WP7? - c#

When I use this task I can't do any thing in my application after saving the contact except showing a messagebox with a message how can I return again to my application when this task completed !!

This should work out the box. When task is finished your application takes control again. You can control task result using Completed event handler
this.saveContactTask.Completed += new EventHandler<SaveContactResult>(saveContactTask_Completed);
private void saveContactTask_Completed(object sender, SaveContactResult e)
{
switch (e.TaskResult)
{
case TaskResult.OK:
MessageBox.Show("Contact is successfully saved.");
break;
case TaskResult.Cancel:
MessageBox.Show("The user canceled the task.");
break;
case TaskResult.None:
MessageBox.Show("NO information regarding the task result is available.");
break;
}
}
Here you can find fully functional example which works exactly as you want. You may take a look and compare with your implementation
http://windowsphonegeek.com/tips/8-How-to-use-SaveContactTask-in-Windows-Phone-Mango

Related

Xamarin: Is there a Way to Differentiate Between a Swipe and a BottomNavigationView Click?

I am wondering if it's possible to differentiate between a swipe and a click on the BottomNavigationView in Xamarin.Android.
I've implemented:
void NavigationView_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
if (_viewPager.CurrentItem == 0)
{
_fm1.Pop2Root();
}
_viewPager.SetCurrentItem(e.Item.Order, true);
}
but there is no differentiation between a swipe and a click. I want to keep the current page loaded if the user swipes, but pop to the root if the user has clicked on the currently selected BottomNavigationView tab.
And here's what my Pop2Root method looks like (not that it really matters):
public void Pop2Root()
{
_wv.LoadUrl("https://www.bitchute.com/");
}
I just want a separate event for click versus swipe.
I'm not looking for anyone to do my work. I will post the full solution (as always) once I've figured it out. What I'm looking for is a yes or no answer whether or not it's possible; then I'll take care of the rest. I've implemented a click listener on the TabHost before, but that's a completely different UI element:
https://github.com/hexag0d/BitChute_Mobile_Android_a2/blob/2.7641/Activities/ClickListeners.cs
If you would like more context on the complete project, here's the MainActivity.cs then you can back into the rest:
https://github.com/hexag0d/BitChute_Mobile_Android_BottomNav/blob/master/MainActivity.cs
Thanks, in advance
The answer to this question is yes. The ViewPager_PageSelected method is invoked when user swipes. The NavigationView_NavigationItemSelected is invoked on a tab press. Interestingly, if ViewPager_PageSelected method is put before NavigationView_NavigationItemSelected method, ViewPager_PageSelected won't be invoked when the user presses the a tab until after this method is called:
_viewPager.SetCurrentItem(e.Item.Order, true);
After that happens, the ViewPager_PageSelected method is invoked and NavigationView_NavigationItemSelected gets invoked again. So I decided to do the order like this and set a custom int. This way, both methods are only called once per user interaction, and there is differentiation.
(Note events BottomNavigationView.NavigationItemSelectedEventArgs & ViewPager.PageSelectedEventArgs)
//put all of this inside your MainActivity.cs
int _tabSelected;
void NavigationView_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
if (_tabSelected == e.Item.Order)
{
switch (_viewPager.CurrentItem)
{
case 0:
_fm1.Pop2Root();
break;
case 1:
_fm2.Pop2Root();
break;
case 2:
_fm3.Pop2Root();
break;
case 3:
_fm4.Pop2Root();
break;
case 4:
_fm5.Pop2Root();
break;
}
}
else
{
_viewPager.SetCurrentItem(e.Item.Order, true);
}
}
private void ViewPager_PageSelected(object sender, ViewPager.PageSelectedEventArgs e)
{
_menu = _navigationView.Menu.GetItem(e.Position);
_navigationView.SelectedItemId = _menu.ItemId;
_tabSelected = _viewPager.CurrentItem;
}

Form is displaying before async function completes

I've got a WinForms project that scans a given network and returns valid IP addresses. Once all the addresses are found, I create a user control for each and place it on the form. My functions to ping ip addresses use async and Task which I thought would "wait" to execute before doing something else, but it doesn't. My form shows up blank, then within 5 seconds, all the user controls appear on the form.
Declarations:
private List<string> networkComputers = new List<string>();
Here's the Form_Load event:
private async void MainForm_Load(object sender, EventArgs e)
{
//Load network computers.
await LoadNetworkComputers();
LoadWidgets();
}
The LoadNetworkComputers function is here:
private async Task LoadNetworkComputers()
{
try
{
if (SplashScreenManager.Default == null)
{
SplashScreenManager.ShowForm(this, typeof(LoadingForm), false, true, false);
SplashScreenManager.Default.SetWaitFormCaption("Finding computers");
}
else
Utilities.SetSplashFormText(SplashForm.SplashScreenCommand.SetLabel, "Scanning network for computers. This may take several minutes...");
networkComputers = await GetNetworkComputers();
}
catch (Exception e)
{
MessageBox.Show(e.Message + Environment.NewLine + e.InnerException);
}
finally
{
//Close "loading" window.
SplashScreenManager.CloseForm(false);
}
}
And the last 2 functions:
private async Task<List<string>> GetNetworkComputers()
{
networkComputers.Clear();
List<string> ipAddresses = new List<string>();
List<string> computersFound = new List<string>();
for (int i = StartIPRange; i <= EndIPRange; i++)
ipAddresses.Add(IPBase + i.ToString());
List<PingReply> replies = await PingAsync(ipAddresses);
foreach(var reply in replies)
{
if (reply.Status == IPStatus.Success)
computersFound.Add(reply.Address.ToString());
}
return computersFound;
}
private async Task<List<PingReply>> PingAsync(List<string> theListOfIPs)
{
var tasks = theListOfIPs.Select(ip => new Ping().SendPingAsync(ip, 2000));
var results = await Task.WhenAll(tasks);
return results.ToList();
}
I'm really stuck on why the form is being displayed before the code in the MainForm_Load event finishes.
EDIT
I forgot to mention that in the LoadNetworkComputers it loads a splash form which lets the user know that the app is running. It's when the form shows up behind that, that I'm trying to avoid. Here's a screenshot (sensitive info has been blacked out):
The reason one would use async-await is to enable callers of functions to continue executing code whenever your function has to wait for something.
The nice thing is that this will keep your UI responsive, even if the awaitable function is not finished. For instance if you would have a button that would LoadNetworkComputers and LoadWidgets you would be glad that during this relatively long action your window would still be repainted.
Since you've defined your Mainform_Loadas async, you've expressed that you want your UI to continue without waiting for the result of LoadNetWorkComputers.
In this interview with Eric Lippert (search in the middle for async-await) async-await is compared with a a cook making dinner. Whenever the cook finds that he has to wait for the bread to toast, he starts looking around to see if he can do something else, and starts doing it. After a while when the bread is toasted he continues preparing the toasted bread.
By keeping the form-load async, your form is able to show itself, and even show an indication that the network computers are being loaded.
An even nicer method would be to create a simple startup-dialog that informs the operator that the program is busy loading network computers. The async form-load of this startup-dialog could do the action and close the form when finished.
public class MyStartupForm
{
public List<string> LoadedNetworkComputers {get; private set;}
private async OnFormLoad()
{
// start doing the things async.
// keep the UI responsive so it can inform the operator
var taskLoadComputers = LoadNetworkComputers();
var taskLoadWidgets = LoadWidgets();
// while loading the Computers and Widgets: inform the operator
// what the program is doing:
this.InformOperator();
// Now I have nothing to do, so let's await for both tasks to complete
await Task.WhenAll(new Task[] {taskLoadComputers, taskLoadWidgets});
// remember the result of loading the network computers:
this.LoadedNetworkComputers = taskLoadComputers.Result;
// Close myself; my creator will continue:
this.Close();
}
}
And your main form:
private void MainForm_Load(object sender, EventArgs e)
{
// show the startup form to load the network computers and the widgets
// while loading the operator is informed
// the form closes itself when done
using (var form = new MyStartupForm())
{
form.ShowDialog(this);
// fetch the loadedNetworkComputers from the form
var loadedNetworkComputers = form.LoadedNetworkComputers;
this.Process(loadedNetworkComputers);
}
}
Now while loading, instead of your mainform the StartupForm is shown while the items are loaded.. The operator is informed why the main form is not showing yet. As soon as loading is finished, the StartupForm closes itself and loading of the main form continues
My form shows up blank, then within 5 seconds, all the user controls appear on the form.
This is by design. When the UI framework asks your app to display a form, it must do so immediately.
To resolve this, you'll need to decide what you want your app to look like while the async work is going on, initialize to that state on startup, and then update the UI when the async work completes. Spinners and loading pages are a common choice.

Execute commands with speech asynchronously

We have our thesis revision and one panelist said that to make our speech recognition system better is to add a way to process a command.
For example if i give a default command
case "What time is it?":
WVASRS.Speak("time");
break;
I want the system to be able to tell the user that the COMMAND is still processing before the user can give another command. Something like:
//I will give a command while the the other command is processing
case "What day is it":
WVASRS.Speak("day");
break;
WVASRS.Speak("Another command is still processing. Please Wait for a few seconds before you can give another command.");
Well, if found something on MSDN but it just does nothing. here is the snippet:
// Assign input to the recognizer and start asynchronous
// recognition.
recognizer.SetInputToDefaultAudioDevice();
completed = false;
Console.WriteLine("Starting asynchronous recognition...");
recognizer.RecognizeAsync(RecognizeMode.Multiple);
// Wait 30 seconds, and then cancel asynchronous recognition.
Thread.Sleep(TimeSpan.FromSeconds(30));
recognizer.RecognizeAsyncCancel();
// Wait for the operation to complete.
while (!completed)
{
Thread.Sleep(333);
}
Console.WriteLine("Done.");
The code from MSDN is more or less correct, you just miss the handler of recognized command, see the complete example here:
recognizer.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
and later
// Handle the SpeechRecognized event.
static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (actionRunning) {
speak("Busy");
}
if (e.Result.Text.Equals("what is the time")) {
actionRunning = true;
startAction()
}
Console.WriteLine("Speech recognized: " + e.Result.Text);
}

Is it possible to show a wait message while a semaphore is locked in C#?

I'm currently making a program to simulate a set of ATMs in visual C#. It's supposed to stop somebody accessing their account if it has already been accessed from a different location. Is it possible to show a message that the account has already been accessed while a semaphore is waiting?
Here is the part of the code where the semaphore is used:
private void button1_Click(object sender, EventArgs e)
{
count++;
if (count == 1)
{
account = findAccount();
if (findAccount() != 5)
{
textBox1.Text = "Please Enter Your Pin";
}
else
{
textBox1.Text = "Please Enter Your Account Number";
count = 0;
}
textBox2.Clear();
}
if (count == 2)
{
if (findPin(account) == true)
{
semaphore.WaitOne();
textBox1.Text = "1: Take Out Cash \r\n2: Balance \r\n3: Exit";
}
else
{
semaphore.Release();
textBox1.Text = "Please Enter Your Account Number";
count = 0;
}
textBox2.Clear();
}
if (count == 3)
{
atm();
}
if (count == 4)
{
withdraw();
}
if (count == 5)
{
int value = Convert.ToInt32(textBox2.Text);
customWithdrawl(value);
}
}
Consider doing two calls to WaitOne. The first call will have a timeout of zero and return a bool that will tell you whether or not you got the semaphore, or someone else still owns it. Two things can happen from there:
1) If someone else owns it, pop up a message that says "Someone else owns the semaphore" and call WaitOne again, but without a timeout (like you're doing now). After the 2nd call to WaitOne returns, close the window that you popped up a second ago..
2) If your call to waitOne with 0 timeout returns true, then you got the semaphore on the 1st try. No need to pop up a window.
Example:
if( semaphore.WaitOne(0) ) //This returns immediately
{
//We own the semaphore now.
DoWhateverYouNeedToDo();
}
else
{
//Looks like someone else already owns the semaphore.
PopUpNotification();
semaphore.WaitOne(); //This one will block until the semaphore is available
DoWhateverYouNeedToDo();
CloseNotification();
}
semaphore.Release();
Note, there are some other issues lurking here.
You probably want to use a try/finally block to release the semaphore to ensure that it gets released across all exception paths.
It's also probably a bad idea to call semaphore.WaitOne() from the GUI thread because the application will become non-responsive while it waits. In fact, you may not see the result of PopUpNotification() if you've hung the GUI thread while doing the 2nd Wait. Consider doing the long wait on a 2nd thread and raising an event back on the GUI thread once you own the semaphore
Consider the following design to resolve Issue 2:
private void button1_Click(object sender, EventArgs e)
{
if(AcquireSemaphoreAndGenerateCallback())
{
//Semaphore was acquired right away. Go ahead and do whatever we need to do
DoWhateverYouNeedToDo();
semaphore.Release()
}
else
{
//Semaphore was not acquired right away. Callback will occur in a bit
//Because we're not blocking the GUI thread, this text will appear right away
textBox1.Text = "Waiting on the Semaphore!";
//Notice that the method returns right here, so the GUI will be able to redraw itself
}
}
//This method will either acquire the semaphore right away and return true, or
//have a worker thread wait on the semaphore and return false. In the 2nd case,
//"CallbackMethod" will run on the GUI thread once the semaphore has been acquired
private void AcquireSemaphoreAndGenerateCallback()
{
if( semaphore.WaitOne(0) ) //This returns immediately
{
return true; //We have the semaphore and didn't have to wait!
}
else
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Waiter));
return false; //Indicate that we didn't acquire right away
}
}
//Wait on the semaphore and invoke "CallbackMethod" once we own it. This method
//is meant to run on a background thread.
private void Waiter(object unused)
{
//This is running on a separate thread
Semaphore.WaitOne(); //Could take a while
//Because we're running on a separate thread, we need to use "BeginInvoke" so
//that the method we're calling runs on the GUI thread
this.BeginInvoke(new Action(CallbackMethod));
}
private void CallbackMethod()
{
textBox1.Text = string.Empty; //Get rid of the "Waiting For Semaphore" text. Can't do this if we're not running on the GUI thread
DoWhateverYouNeedToDo();
semaphore.Release();
}
Now, this solution could also be fraught with peril. It's kind of hard to follow the execution of the program because it jumps around from method to method. If you have an exception, it could be difficult to recover from and make sure all of your program state is correct. You also have to keep track of things like the account number and the pin numbers through all of these method calls. In order to do that, Waiter and CallbackMethod should probably take some parameter that tracks this state that gets passed along to each step. There's also no way to abort waiting (a time out). It will probably work, but shouldn't make it into any production code because it would be too difficult to maintain or extend.
If you really wanted to do it right, you should consider encapsulating the ATM logic in an object that will raise events that the GUI can subscribe to. You could have a method like ATM.LogInAsync(Account,Pin) that you could call. This method would return immediately, but some time later, an event on the ATM class like "LogInComplete" would fire. This event would have a custom EventArgs object that would contain data to trace which log-in has occurred (mainly the Account number). This is called the Event-based Asynchronous Pattern
Alternatively, if you're using C# 5.0, you can use the new Async/Await syntax in the AcquireSemaphoreAndGenerateCallback() method. That's probably the easiest way because the compiler will handle most of the complexities for you
Yes, you may show your message/form/messagebox right before the Wait method. Then when it receives the signal to unblock, you hide your message.

c# cross-thread help

I've got some backgroundworker threads that are working on calculations or saving data. Every time a thread is done working I'm first adding a message to a static messagelist and then I'm showing this in a richtextbox.
The message contains the hour, a label, the message and a message type. This message type I'm using to show the message in a specific color.
Now I've got the problem that some times a 2 threads are done at the same time and try to set a message. So I got the cross-thread exception.
I know that I can solve this by using a delegate. But I'm kinda stuck here.
this is how I set my message currently:
private void SetMessages()
{
rtxtMessage.Text = "";
foreach (var message in GlobalVariables.MessageList)
{
var text = message.Date.ToShortTimeString() + " " + message.Label + ": " +
message.TheMessage;
switch (message.Type)
{
case GlobalVariables.MessageType.normal:
rtxtMessage.SelectionColor = Color.Black;
break;
case GlobalVariables.MessageType.calculation:
rtxtMessage.SelectionColor = Color.Green;
break;
case GlobalVariables.MessageType.error:
rtxtMessage.SelectionColor = Color.Red;
break;
case GlobalVariables.MessageType.warning:
rtxtMessage.SelectionColor = Color.Orange;
break;
default:
break;
}
rtxtMessage.SelectedText = text + Environment.NewLine;
rtxtMessage.ScrollToCaret();
}
pnlMessage.Visible = true;
}
So main question is how can I rewrite this to get it working with a delegate?
I interpret your question as if you are using the BackgroundWorker class for the threaded work. Then then question is how the messages come into the GlobalVariables.MessageList collection. If it is done in the RunWorkerCompleted event, you should not have any cross-threading problems, since it executes on the UI thread (this is the way I would recommend you to do). If it is updated directly from the worker process you will need to take care of synchronization and threading issues yourself (using one of the available locking mechanisms).
Update (after the comment response in the original question):
The RunWorkerCompleted should typically run on the UI thread (or perhaps rather on the thread on which RunWorkerAsync was invoked, I guess), so you should typically not need to bother about threading issues when updating the UI from that thread. However, to be really sure, you can use the following approach:
private void BackgroundWorker_RunWorkerCompleted(object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(
new Action<object, RunWorkerCompletedEventArgs>(
BackgroundWorker_RunWorkerCompleted), sender, e);
}
else
{
// update the message list, and then call SetMessages()
SetMessages();
}
}
That said, I would urge you to pinpoint under exactly which circumstances the threading exception occurs, since it should really not happen using the RunWorkerCompleted event. I ran a test where I started a large (a couple of hundred) number of backgroundworkers simultaneously, and failed to provoke any sort of collision. It also did not use the Invoke-path in the above code sample once.
As a side note I think that you would not need to first store the messages in a list, just to clear and re-populate the textbox with all messages each time. I think you could instead change the SetMessages method into a method that takes a message as paramter and that simply adds the message to the textbox:
private void SetMessage(MyMessage message)
{
var text = message.Date.ToShortTimeString() + " " + message.Label + ": " + message.TheMessage;
switch (message.Type)
{
case GlobalVariables.MessageType.normal:
rtxtMessage.SelectionColor = Color.Black;
break;
case GlobalVariables.MessageType.calculation:
rtxtMessage.SelectionColor = Color.Green;
break;
case GlobalVariables.MessageType.error:
rtxtMessage.SelectionColor = Color.Red;
break;
case GlobalVariables.MessageType.warning:
rtxtMessage.SelectionColor = Color.Orange;
break;
default:
break;
}
rtxtMessage.SelectedText = text + Environment.NewLine;
rtxtMessage.ScrollToCaret();
pnlMessage.Visible = true;
}
You should be able to call this method straight from the RunWorkerCompleted event handler and just pass the message into the method.
You should be able to get this working by locking your static Message List like:
private void SetMessages()
{
rtxtMessage.Text = "";
lock(GlobalVariables.MessageList)
{
foreach (var message in GlobalVariables.MessageList)
{
//Rest of your code
}
pnlMessage.Visible = true;
}
}

Categories