AutoResetEvent in Windows Phone project - can't invoke handler - c#

It's from Windows Phone project. I am trying to invoke few handlers, handler by handler to receive information about GPS / Reverse position. I wonder why it won't run correctly.
When I setup only 1 coordinate it's ok. I have message with Street etc. But when there is more coordinates my handler isn't invoke.
private async void SimulationResults()
{
done = new AutoResetEvent(true);
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
myCoordinate = new GeoCoordinate(51.751985, 19.426515);
if (myMap.Layers.Count() > 0) myMap.Layers.Clear();
mySimulation = new List<SimulationItem>();
mySimulation = Simulation.SimulationProcess(myCoordinate, 120); // Odległość
for(int i = 0; i<2; i++)
{
done.WaitOne();
if (mySimulation.ElementAt(i).Id == 1 | mySimulation.ElementAt(i).Id == -1)
{
// Oczekiwanie, ponieważ obiekt jest zasygnalizowany od razu wejdziemy
// do sekcji krytycznej
AddMapLayer(mySimulation.ElementAt(i).Coordinate, Colors.Yellow, false);
myReverseGeocodeQuery_1 = new ReverseGeocodeQuery();
myReverseGeocodeQuery_1.GeoCoordinate = mySimulation.ElementAt(i).Coordinate;
myReverseGeocodeQuery_1.QueryCompleted += ReverseGeocodeQuery_QueryCompleted_1;
// Sekcja krytyczna
done.Reset(); // Hey I'm working, wait!
myReverseGeocodeQuery_1.QueryAsync();
}
}
MessageBox.Show("Skonczylem");
}
private void ReverseGeocodeQuery_QueryCompleted_1(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
done.Set();
if (e.Error == null)
{
if (e.Result.Count > 0)
{
MapAddress address = e.Result[0].Information.Address;
MessageBox.Show("Wykonano "+address.Street);
}
}
}

What's happening here is that you are blocking on your AutoResetEvent on the UI thread, but that's the same thread that the ReverseGeocodeQuery is trying to run on. Since it's blocked it can't run and it also can't invoke your callback.
A very quick fix that doesn't change your flow too much and assumes some sort of "on everything complete do X" requirement is below. I triggered the whole thing on a background thread with:
new Thread(new ThreadStart(() =>
{
SimulationResults();
})).Start();
Since all of the below is on a background thread I needed to add some Dispatcher.BeginInvoke() calls around anything that called into the UI thread, but this way the thread that is blocked is your background thread and not your UI thread.
AutoResetEvent done;
int remaining;
private async void SimulationResults()
{
done = new AutoResetEvent(true);
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
var myCoordinate = new GeoCoordinate(51.751985, 19.426515);
var mySimulation = new List<GeoCoordinate>()
{
new GeoCoordinate(51.751985, 19.426515),
new GeoCoordinate(2, 2)
};
//mySimulation = Simulation.SimulationProcess(myCoordinate, 120); // Odległość
remaining = mySimulation.Count;
for (int i = 0; i < mySimulation.Count; i++)
{
done.WaitOne();
//if (mySimulation.ElementAt(i).Id == 1 | mySimulation.ElementAt(i).Id == -1)
//{
// Oczekiwanie, ponieważ obiekt jest zasygnalizowany od razu wejdziemy
// do sekcji krytycznej
//AddMapLayer(mySimulation.ElementAt(i).Coordinate, Colors.Yellow, false);
var tempI = i;
Dispatcher.BeginInvoke(() =>
{
var myReverseGeocodeQuery_1 = new ReverseGeocodeQuery();
myReverseGeocodeQuery_1.GeoCoordinate = mySimulation.ElementAt(tempI);
myReverseGeocodeQuery_1.QueryCompleted += ReverseGeocodeQuery_QueryCompleted_1;
// Sekcja krytyczna
done.Reset(); // Hey I'm working, wait!
myReverseGeocodeQuery_1.QueryAsync();
});
//}
}
}
private void ReverseGeocodeQuery_QueryCompleted_1(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
done.Set();
remaining--;
if (e.Error == null)
{
if (e.Result.Count > 0)
{
MapAddress address = e.Result[0].Information.Address;
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Wykonano " + address.Street);
});
}
}
if (remaining == 0)
{
// Do all done code
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Skonczylem");
});
}
}
Alternatively you could also make this a proper async method that awaits on different events to progress.

Related

FTDI Multithreaded Read

I have the following problem and hope someone can help me.
My basic flow: I want to program any number of devices in parallel using the FTDI D2XX driver and then communicate with them for testing purposes. For this I use two arrays from BackgroundWorker - the first array for programming and the second for testing.
Programming works without any problems. But if I start the BackgroundWorker from the second array to start the test, the connection fails. If I run the complete sequence with only one BackgroundWorker for programming and one BackgroundWorker for testing, the sequence works without problems.
Initialization of BackgroundWorker
private void InitializeBackgoundWorkers()
{
for (var f = 0; f < ftdiDeviceCount; f++)
{
threadArrayProgram[f] = new BackgroundWorker();
threadArrayProgram[f].DoWork += new DoWorkEventHandler(bgr_WorkerStirrerProg_DoWork);
threadArrayProgram[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerProgRunWorkerCompleted);
threadArrayProgram[f].WorkerReportsProgress = true;
threadArrayProgram[f].WorkerSupportsCancellation = true;
}
for (var f = 0; f < ftdiDeviceCount; f++)
{
threadArrayTest[f] = new BackgroundWorker();
threadArrayTest[f].DoWork += new DoWorkEventHandler(bgr_WorkerStirrerTest_DoWork);
threadArrayTest[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerTestRunWorkerCompleted);
threadArrayTest[f].WorkerReportsProgress = true;
threadArrayTest[f].WorkerSupportsCancellation = true;
}
}
Aufruf der BackgroundWorker
private void button2_Click_1(object sender, EventArgs e)
{
if (!bStirrerSerached)
{
vSetProgressBarValueRuehrer(1, imaxprogressbar);
vSearchStirrer();
}
if (FtStatus == FTDI.FT_STATUS.FT_OK)
{
//bgr_Worker_Stirrer.RunWorkerAsync();
InitializeBackgoundWorkers();
//---programmieren---//
for (var f = 0; f < /*FilesToProcess*/ftdiDeviceCount; f++)
{
var fileProcessed = false;
while (!fileProcessed)
{
for (var threadNum = 0; threadNum < MaxThreads; threadNum++)
{
if (!threadArrayProgram[threadNum].IsBusy)
{
Console.WriteLine("Starting Thread: {0}", threadNum);
stemp = "Starting Thread: " + threadNum;
File.AppendAllText(slogfile, stemp);
threadArrayProgram[threadNum].RunWorkerAsync(f);
fileProcessed = true;
Thread.Sleep(1000);
break;
}
}
if (!fileProcessed)
{
Thread.Sleep(50);
}
}
}
//---testen---//
for (var f = 0; f < /*FilesToProcess*/ftdiDeviceCount; f++)
{
var fileProcessed = false;
while (!fileProcessed)
{
for (var threadNum = 0; threadNum < MaxThreads; threadNum++)
{
if (!threadArrayTest[threadNum].IsBusy)
{
Console.WriteLine("Starting Thread: {0}", threadNum);
stemp = "Starting Thread: " + threadNum;
File.AppendAllText(slogfile, stemp);
threadArrayTest[threadNum].RunWorkerAsync(f);
fileProcessed = true;
Thread.Sleep(1000);
break;
}
}
if (!fileProcessed)
{
Thread.Sleep(50);
}
}
}
}
button2.Enabled = false;
}
BackgroundWorker
private void bgr_WorkerStirrerProg_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if (FtStatus == FTDI.FT_STATUS.FT_OK)
{
if (ftdiDeviceList != null)
{
//---db werte sammeln---//
cRuehrerProp = new CRuehrerProperties();
cRuehrerProp.SBenutzer = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
cRuehrerProp.SComputername = System.Windows.Forms.SystemInformation.ComputerName.ToString();
//---Rührer programmieren---//
vStirrerProgram((int)e.Argument);
}
}
}
catch (NotSupportedException /*exc*/)
{
}
finally
{
this.Invoke((MethodInvoker)delegate
{
});
}
}
private void bgr_WorkerStirrerTest_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if (!bfinish)
{
while (!bfinish)
{
if (bfinish)
break;
}
}
//---Test starten---//
vStirrerTest((int)e.Argument);
}
catch (NotSupportedException /*exc*/)
{
}
finally
{
this.Invoke((MethodInvoker)delegate
{
button2.Enabled = true;
myFtdiDevice.Close();
});
}
}
Testing method
private void vStirrerTest(int pos)
{
//threadnr
iPosRuehrerGrid = pos;
Console.WriteLine("Thread {0} StirrerTest", pos);
ftStatus = myFtdiDevice.CyclePort();
UInt32 newFtdiDeviceCount = 0;
do
{
// Wait for device to be re-enumerated
// The device will have the same location since it has not been
// physically unplugged, so we will keep trying to open it until it succeeds
ftStatus = myFtdiDevice.OpenByLocation(ftdiDeviceList[iPosRuehrerGrid].LocId);
Console.WriteLine("try to open locid" + ftdiDeviceList[iPosRuehrerGrid].LocId + " on device " + iPosRuehrerGrid);
//ftStatus = myFtdiDevice.OpenByLocation(ftdiDeviceListOrig[iStirrerPosold[iPosRuehrerGrid]].LocId);
Thread.Sleep(1000);
} while (ftStatus != FTDI.FT_STATUS.FT_OK);
// Close the device
myFtdiDevice.Close();
// Re-create our device list
ftStatus = myFtdiDevice.GetNumberOfDevices(ref newFtdiDeviceCount);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
{
// Wait for a key press
Console.WriteLine("Failed to get number of devices (error " + ftStatus.ToString() + ")");
stemp = "Failed to get number of devices (error " + ftStatus.ToString() + ")";
File.AppendAllText(slogfile, stemp);
return;
}
// Re-populate our device list
ftStatus = myFtdiDevice.GetDeviceList(ftdiDeviceList);
bRepopulateList = true;
vSearchStirrer();
The error occurs in the do loop. If I use only one device - and thus only one thread at a time, it takes an average of 5 runs until the device is opened again. However, if I attach another device and thus have 2 programming and 2 test threads, it does not manage to open the desired device.
I have looked at the DeviceList to make sure it is looking for the right device with the right ID - which it is.
Since I don't have any experience with the Backgrounworker yet, I'm not sure if I haven't forgotten something, which is why this error occurs.

Cancel a fuction/process

I currently have a application that pings a list of IPs.
The user clicks a button and it continuously pings all IPS for 20 seconds..
What I want to do is click a button to stop this.
I created a function i called "Process" and it calls this process when the button is clicked.
I tried to create a bool value and while loop for when it's false and made the stop button change the bool value to true, but it doesn't seem to stop anything, in fact I can't even close the window until the ping is completed.
My code is below.
private bool _stopLoop;
private void btnPlay_Click(object sender, EventArgs e)
{
Process();
}
private void Process()
{
while (_stopLoop == false)
{
for (int i = 0; i < 20; i++)
{
foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows)
{
var count = 20;
progressBar1.Value = i * progressBar1.Maximum / count;
Application.DoEvents();
var url = dataGridView1Row.Cells[1].Value.ToString();
int timeout = 500;
Ping ping = new Ping();
PingReply pingreply = ping.Send(url, timeout);
PingReply result = null;
IPStatus status;
result = pingreply;
status = result.Status;
if (status != IPStatus.Success)
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Red;
dataGridView1Row.Cells[0].Value = "Offline";
}
else
{
dataGridView1Row.Cells[0].Style.BackColor = Color.Green;
dataGridView1Row.Cells[0].Value = "Online";
}
}
}
}
}
private void btnStop_Click(object sender, EventArgs e)
{
_stopLoop = true;
}
I am only targeting the direct questions why the loops dont stop. Implementing a background thread or tasks or background worker is a better solution but not the question :)
As in my comment states, you only break out of your "infinite" loop which is the most outer loop.
The two inner loops which run over your IP's ( foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows){ [...] } as well as your "do it for 20 times" loops for (int i = 0; i < 20; i++){ [...] } need to be broken out of if you want it to stop.
this means you can change them like that:
while (_stopLoop == false)
{
for (int i = 0; i < 20; i++)
{
foreach (DataGridViewRow dataGridView1Row in dataGridView1.Rows)
{
if(_stopLoop)
return; // finish execution and jump out of all loops, or use break to jump into the for loop, but then you need to break out of it as well
/* your ping logic */
}
}
}
If you use async/await your GUI can be responsive and your requests can be concurrent at the same time:
private CancellationTokenSource pingCancellation;
private async void btnPlay_Click(object sender, EventArgs e)
{
const int pingTimeout = 500;
var pingDuration = TimeSpan.FromSeconds(20);
btnPlay.Enabled = false;
dataGridView1.ReadOnly = true;
var entries =
dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow)
.Select(row => new { Row = row, Hostname = row.Cells[1].Value.ToString(), Ping = new Ping() })
.ToList();
pingCancellation = new CancellationTokenSource();
pingCancellation.Token.Register(() => entries.ForEach(e => e.Ping.SendAsyncCancel()));
btnStop.Enabled = true;
pingCancellation.CancelAfter(pingDuration);
var finishTime = DateTime.UtcNow.Add(pingDuration);
try
{
while (!pingCancellation.IsCancellationRequested)
{
await Task.WhenAll(entries.Select(async e =>
{
var result = await e.Ping.SendPingAsync(e.Hostname, pingTimeout);
if (result.Status != IPStatus.Success)
{
e.Row.Cells[0].Style.BackColor = Color.Red;
e.Row.Cells[0].Value = "Offline";
}
else
{
e.Row.Cells[0].Style.BackColor = Color.Green;
e.Row.Cells[0].Value = "Online";
}
}).Concat(new[] { Task.Delay(pingTimeout, pingCancellation.Token) /*Rate limiting*/ }));
progressBar1.Value = (int)Math.Min(progressBar1.Maximum * (pingDuration - (finishTime - DateTime.UtcNow)).Ticks / pingDuration.Ticks, progressBar1.Maximum);
}
}
catch (TaskCanceledException)
{
}
btnStop.Enabled = false;
pingCancellation.Dispose();
pingCancellation = null;
foreach (var entry in entries)
{
entry.Ping.Dispose();
}
progressBar1.Value = 0;
dataGridView1.ReadOnly = false;
btnPlay.Enabled = true;
}
private void btnStop_Click(object sender, EventArgs e)
{
if (pingCancellation != null && !pingCancellation.IsCancellationRequested)
{
pingCancellation.Cancel();
}
}

Google url scraping not looping lines in list box

I am trying to scrape results from google search, the tool need to browse pages one by one. However the issue is its not taking the all the list from the listbox. Its just working for the first line of the list box.
Startbtn Code
foreach (string url in urlList.Items)
{
webBrowser1.Navigate("https://www.google.com/search?q=" + url);
await PageLoad(30, 5);
MessageBox.Show("sdsaD3");
string pageSource = webBrowser1.DocumentText;
Scrape(pageSource);
}
--
Scrape Method
private async void Scrape(string pageSource)
{
string regexExpression = "(?<=><div class=\"rc\"><div class=\"r\"><a href=\")(.*?)(?=\" onmousedown=)";
Regex match = new Regex(regexExpression, RegexOptions.Singleline);
MatchCollection collection = Regex.Matches(pageSource, regexExpression);
for (int i = 0; i < collection.Count; i++)
{
CommonCodes.WriteToTxt(collection[i].ToString(), "googlescrapedurls.txt");
if (i == collection.Count - 1)
{
var elementid = webBrowser1.Document.GetElementById("pnnext");
if (elementid != null)
{
for (int w = 0; w < 1; w++)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
worker.RunWorkerAsync(w);
}
}
else if(webBrowser1.Document.GetElementById("pnnext") == null)
{
for(int pg=0; pg< urlList.Items.Count; pg++)
{
webBrowser1.Navigate("https://www.google.com/search?q=" + urlList.Items[pg+1]);
CommonCodes.WaitXSeconds(10);
//await PageLoad(30, 5);
Scrape(webBrowser1.DocumentText);
}
}
}
}
--
Background worker code:
BackgroundWorker backgroundWorker = sender as BackgroundWorker;
webBrowser1.Invoke(new Action(() => { gCaptcha(); }));
webBrowser1.Invoke(new Action(() => { webBrowser1.Document.GetElementById("pnnext").InvokeMember("Click"); }));
await PageLoad(30, 5);
webBrowser1.Invoke(new Action(() => { Scrape(webBrowser1.DocumentText); }));
pageload code
try
{
TaskCompletionSource<bool> PageLoaded = null;
PageLoaded = new TaskCompletionSource<bool>();
int TimeElapsed = 0;
webBrowser1.DocumentCompleted += (s, e) =>
{
if (webBrowser1.ReadyState != WebBrowserReadyState.Complete) return;
if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult(true);
};
//
while (PageLoaded.Task.Status != TaskStatus.RanToCompletion)
{
await Task.Delay(delay * 1000);//interval of 10 ms worked good for me
TimeElapsed++;
if (TimeElapsed >= TimeOut * 100) PageLoaded.TrySetResult(true);
}
}
catch (Exception ex)
{
CommonCodes.WriteLog(ex.ToString());
MessageBox.Show(ex.Message);
}
--
The main problem is when I have 5 lines in listbox, for the first line only it is going to every page and scraping urls but for the other lines its not working properly. I don't understand the problem with in the code. Some how the code
MessageBox.Show("sdsaD3");
executing multiple time(If 5 lines in listbox then this msg boxpoping up 5 times). Thanks for the help.
EDit: I found the issue, it seems the issue is with await PageLoad(30, 5); but I am not sure how to invoke async method. Any one have idea?

Cefsharp Offscreen EvaluateScriptAsync

I was using Cefsharp Winforms, and recently I've been trying to switch to Offscreen. Everything works just fine, except now my code doesn't wait for EvaluateScriptAsync to complete before returns the page's source.
Or maybe I am just not quite understand how this task thing is working. Here is my progress so far:
private static void WebBrowserFrameLoadEnded(object sender, FrameLoadEndEventArgs e)
{
var browser = (CefSharp.OffScreen.ChromiumWebBrowser)sender;
if (e.Frame.IsMain)
{
browser.FrameLoadEnd -= WebBrowserFrameLoadEnded;
var x = browser.EvaluateScriptAsync("/* some javascript codes */");
if (x.IsCompleted && x.Result.Success)
{
x.ContinueWith(a =>
{
var task = browser.GetSourceAsync();
task.ContinueWith(d =>
{
if (d.IsCompleted)
{
globalRtnVal = d.Result;
}
}).ConfigureAwait(false);
});
}
}
}
And my main code is like this:
/* some codes */
CefSharp.OffScreen.ChromiumWebBrowser asd = new CefSharp.OffScreen.ChromiumWebBrowser(/* url */);
asd.BrowserSettings.Javascript = CefSharp.CefState.Enabled;
asd.BrowserSettings.WebSecurity = CefSharp.CefState.Disabled;
asd.FrameLoadEnd += WebBrowserFrameLoadEnded;
int tryCount = 0;
do
{
Thread.Sleep(3000);
RtnHtml = globalRtnVal;
if (String.IsNullOrEmpty(RtnHtml))
tryCount++;
if (tryCount == 10 && String.IsNullOrEmpty(RtnHtml))
{
/* some codes */
return null;
}
}
while (String.IsNullOrEmpty(RtnHtml));
/* some codes */

why do other events cannot be fired while "for loop" is in process?

I have a for loop and when the loop is being processed, I cant access any other function or event like clicking button it doesn't work till the for loop ends. Is there any way to overcome this Issue and hope I can get answer soon.
for (int i = 0; i < sizes - 2; i++)
{
if (pictureBox1.Image != null)
{
trackBar1.Value = trackBar1.Value + 1;
DisplayImage(_image);
}
}
Thanks in advance.
hi if you using framework 4.5
you can to the next :
Task.Run(() =>
{
for (int i = 0; i < sizes - 2; i++)
{
if (pictureBox1.Image != null)
{
trackBar1.Value = trackBar1.Value + 1;
DisplayImage(_image);
}
}
});
if not you can try this using thread :
Thread thread = new Thread(NewMethod);
thread.Start();
private void NewMethod()
{
for (int i = 0; i < sizes - 2; i++)
{
if (pictureBox1.Image != null)
{
trackBar1.Value = trackBar1.Value + 1;
DisplayImage(_image);
}
}
}
you can upgrade but you need to do it with delegate try this if you have cross thread operation error when update ui :
create delegate void function
delegate void Function();
then in your for make this :
Invoke(new Function(delegate()
{
label.text = "some text" ;
}));
This example shows how to create a new thread in .NET Framework. First, create a new ThreadStart delegate. The delegate points to a method that will be executed by the new thread. Pass this delegate as a parameter when creating a new Thread instance. Finally, call the Thread.Start method to run your method (in this case WorkThreadFunction) on background.
using System.Threading;
Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
thread.Start();
The WorkThreadFunction could be defined as follows.
public void WorkThreadFunction()
{
try
{
// do any background work
}
catch (Exception ex)
{
// log errors
}
}

Categories

Resources