As title, how to release thread is required in multiple thread ?
Ex : I have 5 thread is waiting. I only want thread position 3 is released
I use autoresetevent/manualresetevent/monitor.wait and monitor.pulse but all release thread follow FIFO
help me !!!
UPDATED:
This is form1:
private BackgroundWorker[] threadArray;
public static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
private void btn_Start_Scraping_Click(object sender, EventArgs e)
{
threadArray = new BackgroundWorker[listView_Site.Items.Count];
for (var f = 0; f < listView_Site.Items.Count; f++)
{
threadArray[f] = new BackgroundWorker();
threadArray[f].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork);
threadArray[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted);
threadArray[f].ProgressChanged += new ProgressChangedEventHandler(BackgroundWorkerFilesProgressChanged);
threadArray[f].WorkerReportsProgress = true;
threadArray[f].WorkerSupportsCancellation = true;
threadArray[f].RunWorkerAsync(listView_Site.Items[f].Tag.ToString());
}
}
private void BackgroundWorkerFilesDoWork(object sender, DoWorkEventArgs e)
{
....// all above code is fine
requestCaptcha = (HttpWebRequest)WebRequest.Create(uriCaptchaPage);
requestCaptcha.Pipelined = true;
requestCaptcha.KeepAlive = true;
requestCaptcha.AllowAutoRedirect = false;
//request.Proxy = null;
requestCaptcha.Timeout = 60000;
requestCaptcha.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
requestCaptcha.CookieContainer = sessionID;
request.ServicePoint.Expect100Continue = false;
requestCaptcha.Method = "GET";
requestCaptcha.Referer = uriloginPage.AbsoluteUri;
//get response.
responseCaptcha = (HttpWebResponse)requestCaptcha.GetResponse();
Stream imagestream = responseCaptcha.GetResponseStream();
if (imagestream != null)
{
Image image = Image.FromStream(imagestream);
if (Directory.Exists(Application.StartupPath + "\\Captcha") == false)
{
Directory.CreateDirectory(Application.StartupPath + "\\Captcha");
}
switch (responseCaptcha.ContentType)
{
case "image/jpeg":
{
saveLocation += ".jpg";
if (File.Exists(saveLocation))
{
File.Delete(saveLocation);
}
image.Save(saveLocation,ImageFormat.Jpeg);
break;
}
case "image/gif":
{
saveLocation += ".gif";
if (File.Exists(saveLocation))
{
File.Delete(saveLocation);
}
image.Save(saveLocation, ImageFormat.Gif);
break;
}
case "image/png":
{
saveLocation += ".png";
if (File.Exists(saveLocation))
{
File.Delete(saveLocation);
}
image.Save(saveLocation, ImageFormat.Png);
break;
}
}
//show form2 to enter captcha
lock (_lockObj)
{
if (Application.OpenForms.OfType<frmCaptchaQuestion>().Any() == false)
{
DoOnUIThread(delegate()
{
_formCaptchaQuestion.CreatePanelCaptcha(uriloginPage, saveLocation,idHomePage);
_formCaptchaQuestion.Show();
});
}
else
{
DoOnUIThread(() => _formCaptchaQuestion.CreatePanelCaptcha(uriloginPage, saveLocation,idHomePage));
}
}
//wait and get captcha from form2 and only run thread is required
//this is my problem <<<<========================================
lock (_lockObj)
{
//_manualResetEvent.WaitOne(30000);
//_manualResetEvent.Reset();
//if (clsValueStatic.CaptchaText != null)
//{
// foreach (var id in clsValueStatic.CaptchaText)
// {
while (!_go)
{
Monitor.Wait(_lockObj);
}
// }
//}
}
requestCaptcha = (HttpWebRequest)WebRequest.Create(uriActionLoginPage);
requestCaptcha.Pipelined = true;
requestCaptcha.KeepAlive = true;
requestCaptcha.AllowAutoRedirect = false;
//request.Proxy = null;
requestCaptcha.Timeout = 60000;
requestCaptcha.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
requestCaptcha.CookieContainer = sessionID;
request.ServicePoint.Expect100Continue = false;
requestCaptcha.Method = "GET";
}
Form2:
private void textBoxCaptcha_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
var textBox = sender as TextBoxX;
if (textBox != null)
{
clsValueStatic.CaptchaText = textBox.Text.Trim();
textBox.Parent.Parent.Dispose();
frmScrapingAnalysis._manualResetEvent.Set();
}
}
}
PS : Form1 have 1 button to start multiple backgroundworker and show form2 then all backgroundworker wait to get text captcha of textbox from form2
my way want when user enter text of backgroundworker is shown on form2 then only the backgroundworker is released. All other backgroundworker still wait
Related
using System;
using System.ComponentModel;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net;
namespace Seranking_Scraper
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
btnStop.Enabled = false;
}
CancellationTokenSource cts = null;
List<string> proxyList = new List<string>();
int _proxyIndex = 0;
int retries = 0;
int linesCount = 1;
int totalLinesCount;
List<Task> tasks = null;
string regex = "XXXXXX";
private static HttpClient client = null;
private async void BtnStart_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Clear();
cts = new CancellationTokenSource();
btnStart.Enabled = false;
btnStop.Enabled = true;
btnExport.Enabled = false;
btnOpen.Enabled = false;
btnClear.Enabled = false;
totalLinesCount = listBox_domains.Items.Count;
List<string> urls = new List<string>();
for (int i = 0; i < listBox_domains.Items.Count; i++)
{
urls.Add(listBox_domains.Items[i].ToString());
}
if (textBox_Proxies.Text != null)
{
for (int i = 0; i < textBox_Proxies.Lines.Length; i++)
{
proxyList.Add(textBox_Proxies.Lines[i]);
}
}
var maxThreads = (int)numericUpDown1.Value;
var q = new ConcurrentQueue<string>(urls);
tasks = new List<Task>();
for (int n = 0; n < maxThreads; n++)
{
tasks.Add(Task.Run(async () =>
{
while (q.TryDequeue(out string url))
{
await SendHttpRequestAsync(url, cts.Token);
Thread.Sleep(1);
if (cts.IsCancellationRequested)
{
break;
}
foreach (Task eTask in tasks)
{
if (eTask.IsCompleted)
eTask.Dispose();
}
}
}, cts.Token));
}
await Task.WhenAll(tasks).ContinueWith((FinalWork) =>
{
Invoke(new Action(() =>
{
btnStart.Enabled = true;
btnExport.Enabled = true;
btnOpen.Enabled = true;
btnClear.Enabled = true;
timer1.Enabled = false;
timer1.Stop();
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Invoke((Action)(() => progressBar1.Value = 100));
if(!cts.IsCancellationRequested)
MessageBox.Show(new Form { TopMost = true }, "Completed!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}));
}, TaskContinuationOptions.OnlyOnRanToCompletion);
//var options = new ParallelOptions()
//{
// MaxDegreeOfParallelism = (int)numericUpDown1.Value
//};
//Parallel.For(0, listBox_domains.Items.Count, async j =>
//{
// await SendHttpRequestAsync(listBox_domains.Items[j].ToString());
// Thread.Sleep(10);
//});
}
private string GetProxy()
{
if (proxyList.Count <=0) return null;
if (_proxyIndex >= proxyList.Count - 1) _proxyIndex = 0;
var proxy = proxyList[_proxyIndex];
_proxyIndex++;
return proxy;
}
private async Task ToCsV(DataGridView dGV, string filename)
{
await Task.Yield();
string stOutput = "";
// Export titles:
string sHeaders = "";
for (int j = 0; j < dGV.Columns.Count; j++)
sHeaders = sHeaders.ToString() + Convert.ToString(dGV.Columns[j].HeaderText) + "\t";
stOutput += sHeaders + "\r\n";
// Export data.
for (int i = 0; i < dGV.RowCount - 1; i++)
{
string stLine = "";
for (int j = 0; j < dGV.Rows[i].Cells.Count; j++)
stLine = stLine.ToString() + Convert.ToString(dGV.Rows[i].Cells[j].Value) + "\t";
stOutput += stLine + "\r\n";
//progressBar1.Style = ProgressBarStyle.Blocks;
//progressBar1.Value = (i / 100) * 100;
}
Encoding utf16 = Encoding.GetEncoding(1254);
byte[] output = utf16.GetBytes(stOutput);
FileStream fs = new FileStream(filename, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(output, 0, output.Length); //write the encoded file
bw.Flush();
bw.Close();
fs.Close();
}
private async Task SendHttpRequestAsync(string url, CancellationToken ct)
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(GetProxy(), false),
UseProxy = true
};
//httpClientHandler.MaxConnectionsPerServer = 1;
httpClientHandler.AllowAutoRedirect = true;
httpClientHandler.MaxAutomaticRedirections = 3;
try
{
using (client = new HttpClient(httpClientHandler))
{
client.Timeout = TimeSpan.FromMilliseconds(1000 * (int)numericUpDown_timeout.Value); //adjust based on your network
client.DefaultRequestHeaders.ConnectionClose = true;
ServicePointManager.DefaultConnectionLimit = 100;
//var byteArray = Encoding.ASCII.GetBytes("username:password1234");
//client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
try
{
using (HttpResponseMessage response = await client.GetAsync("xxxx))
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
//response.Dispose();
string result = await content.ReadAsStringAsync();
Regex match = new Regex(regex, RegexOptions.Singleline);
MatchCollection collection = Regex.Matches(result, regex);
try
{
if (collection.Count > 0)
{
await AddDataToDgv(url, collection[0].ToString(), collection[1].ToString(), collection[2].ToString());
}
else if (result.Contains("No data for your search query"))
{
await AddDataToDgv(url, "nodata", "nodata", "nodata");
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
await AddDataToDgv(url, "errorCount", "errorCount", "errorCount");
}
}
}
else
{
await RetriesProxyFail(url, ct);
}
}
}catch(Exception ex)
{
await RetriesProxyFail(url, ct, ex);
client.Dispose();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public async Task RetriesProxyFail(string url, CancellationToken ct, Exception ex = null)
{
client.DefaultRequestHeaders.ConnectionClose = true;
if (!cts.IsCancellationRequested)
{
retries++;
if (retries > (int)numericUpDown_Retries.Value)
{
retries = 0;
Invoke(new Action(async () =>
{
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
await AddDataToDgv(url, "timeout", "timeout", "timeout");
}));
}
else
{
await SendHttpRequestAsync(url, ct);
}
}
}
public async Task AddDataToDgv(string url, string tcost, string tTraffic, string tValue)
{
try
{
await Task.Yield();
Invoke(new Action(() =>
{
dataGridView1.Rows.Add(url, tcost, tTraffic, tValue);
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
if (Application.RenderWithVisualStyles)
progressBar1.Style = ProgressBarStyle.Marquee;
else
{
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
timer1.Enabled = true;
}
}));
}
catch (Exception ex)
{
Invoke(new Action(async () =>
{
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
await AddDataToDgv(url, "error", "error", "error");
}));
}
}
private void BtnOpen_Click(object sender, EventArgs e)
{
linesCount = 1;
try
{
openFileDialog1.ShowDialog();
openFileDialog1.Title = "Please select text file that contains root domains.";
openFileDialog1.DefaultExt = "txt";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.CheckFileExists = true;
openFileDialog1.CheckPathExists = true;
this.openFileDialog1.Multiselect = true;
myWorker_ReadTxtFile = new BackgroundWorker();
myWorker_ReadTxtFile.DoWork += new DoWorkEventHandler(MyWorker_ReadTxtFile_DoWork);
myWorker_ReadTxtFile.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MyWorker_ReadTxtFile_RunWorkerCompleted);
myWorker_ReadTxtFile.ProgressChanged += new ProgressChangedEventHandler(MyWorker_ReadTxtFile_ProgressChanged);
myWorker_ReadTxtFile.WorkerReportsProgress = true;
myWorker_ReadTxtFile.WorkerSupportsCancellation = true;
listBox_domains.Items.Clear();
foreach (String fileName_Domains in openFileDialog1.FileNames)
{
myWorker_ReadTxtFile.RunWorkerAsync(fileName_Domains);
}
}
catch (Exception ex)
{
}
}
private void OpenFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
private void MyWorker_ReadTxtFile_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
listBox_domains.Items.Add(e.UserState.ToString());
lbl_totallines.Text = "TLines: " + linesCount++.ToString();
}
private void MyWorker_ReadTxtFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
public void ReadLinesToListBox(string fileName_Domains)
{
using (StreamReader sr = File.OpenText(fileName_Domains))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
myWorker_ReadTxtFile.ReportProgress(0, s);
Thread.Sleep(1);
}
}
}
private void MyWorker_ReadTxtFile_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker sendingWorker = (BackgroundWorker)sender;//Capture the BackgroundWorker that fired the event
object fileName_Domains = (object)e.Argument;//Collect the array of objects the we received from the main thread
string s = fileName_Domains.ToString();//Get the string value
ReadLinesToListBox(s);
}
private void Label2_Click(object sender, EventArgs e)
{
}
private void BtnStop_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
cts.Dispose();
btnStart.Enabled = true;
btnStop.Enabled = false;
btnExport.Enabled = true;
btnOpen.Enabled = true;
btnClear.Enabled = true;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = 100;
MessageBox.Show(new Form { TopMost = true }, "Cancelled!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private async void BtnExport_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel Documents (*.xls)|*.xls";
sfd.FileName = "Site Metrics";
if (sfd.ShowDialog() == DialogResult.OK)
{
await ToCsV(dataGridView1, sfd.FileName); // Here dataGridview1 is your grid view name
}
MessageBox.Show(new Form { TopMost = true }, "Exported!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
private void BtnClear_Click(object sender, EventArgs e)
{
listBox_domains.Items.Clear();
dataGridView1.Rows.Clear();
}
private void Form1_Load(object sender, EventArgs e)
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
}
private void BtnPasteProxies_Click(object sender, EventArgs e)
{
textBox_Proxies.Text = Clipboard.GetText();
}
private void Timer1_Tick(object sender, EventArgs e)
{
progressBar1.Value += 5;
if (progressBar1.Value > 100)
progressBar1.Value = 0;
}
}
}
The above code is working fine but the problem is it slowly increasing the memory usage. When I start it use some around 40 mb slowly its increasing I tried memory tests, the increase in memory is slow but its increasing slowly.
Any one help me whats wrong in my code?
I am testing with some 4k urls, when it reaches 2k urls my memory usage is 60 MB. Still increasing slowly.
A slow memory increase is totally normal. .NET uses Garbage Collection Memory Management approach. Now while the collection runs, every other thread has to stop. This can cause human noticeable stalls. And is one big reason GC and realtime programming do not mix that well.
To avoid those stalls, the GC is lazy with running. It is aiming for only running once - at application closure. Delays will not be that noticeable then. And it might even be able to save work, as the memory will be handed back to the OS afterwards and not be reused. Short of running finalizers, there might not be much work to be done.
There are only a few things that can force it to run earlier:
there is a danger of a OutOfMemory exception. The GC will have collected and defragmented everything it possibly could before you ever get that Exception.
you call GC.Collect(); It allows you to force a collection now. Note that this only adviseable for debugging and testing. Production code should not have this
you pick a GC strategy that differs from Desktop applciation default. There are ones that do the reachabiltiy checks in anotehr thread, to have that work not pause all threads. Ones that run regulary but avoid defragmentation. Even ones that run regulary with a upper bound on runtime (to limit the stalls).
I'm having issues with my background worker not completing and subsequently hanging after one run. The background worker handles a program running a linear stage and so it is important that the timing is right (hence all of the Thread.Sleep() calls.)
here is my code:
public MainForm()
{
InitializeComponent();
bgW2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgW2_RunWorkerCompleted);
}
private void bgW2_DoWork(object sender, DoWorkEventArgs e)
{
string program = #"C:\Users\mikegjohn\source\repos\CLL AutoForce\Test.csv";
var stream = new FileStream(program, FileMode.Open, FileAccess.Read);
using (var streamReader = new StreamReader(stream))
{
string ln;
while ((ln = streamReader.ReadLine()) != null)
{
string[] lnArr = ln.Split(',');
switch (lnArr[1])
{
case "0":
sendCommand("L-");
string status = "";
while (status != "0")
{
Thread.Sleep(250);
status = loopCommands("PS");
}
Thread.Sleep(1000);
break;
case "1":
string p = Fn.convertPos(lnArr[3]);
sendCommand("X"+p);
string s = Convert.ToString(Fn.backconvert(loopCommands("PX")));
while (s != lnArr[3])
{
Thread.Sleep(250);
s = Convert.ToString(Fn.backconvert(loopCommands("PX")));
}
Thread.Sleep(1000);
break;
case "2":
Fn.MeasureLabel();
break;
case "3":
sendCommand("HSPD=500000");
Thread.Sleep(500);
sendCommand("LSPD=250000");
Thread.Sleep(500);
sendCommand("X0");
string x = Convert.ToString(Fn.backconvert(loopCommands("PX")));
while (x != lnArr[4])
{
Thread.Sleep(250);
s = Convert.ToString(Fn.backconvert(loopCommands("PX")));
}
Thread.Sleep(1000);
sendCommand("HSPD=250000");
sendCommand("LSPD=50000");
break;
}
}
}
}
private void btnRun_Click(object sender, EventArgs e)
{
bgW2.RunWorkerAsync();
}
private void bgW2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Program completed");
}
The Messagebox.Show never fires. I have taken a look at some other similar issues with this which points mainly to blocking of the UI thread. Can anyone point me in the right direction with this?
You may be missing the DoWork event.
public Form1() {
InitializeComponent();
bgW2.DoWork += new DoWorkEventHandler(bgW2_DoWork) ;
bgW2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgW2_RunWorkerCompleted);
}
https://stackoverflow.com/a/14734610
found my issue - it was a bug in case "3" which i was not picking up
case "3":
sendCommand("HSPD=500000");
Thread.Sleep(500);
sendCommand("LSPD=250000");
Thread.Sleep(500);
sendCommand("X0");
string x = Convert.ToString(Fn.backconvert(loopCommands("PX")));
while (x != lnArr[4])
{
Thread.Sleep(250);
s = Convert.ToString(Fn.backconvert(loopCommands("PX"))); // <-- this does not match the while so it was getting stuck in the loop
}
Thread.Sleep(1000);
sendCommand("HSPD=250000");
sendCommand("LSPD=50000");
break;
I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response
I want to change wpf controls status after click button start.
The picture is what I want.
Following is my code
private bool _bWorking = false;
public delegate void UpdateStatusDelegate();
private void SetStatus(bool bEnable)
{
if (bEnable)
{
tbName.IsReadOnly = false;
barStatus.Visibility = Visibility.Hidden;
btnStart.IsEnabled = true;
btnStop.IsEnabled = false;
btnClose.IsEnabled = true;
}
else
{
tbName.IsReadOnly = true;
barStatus.Visibility = Visibility.Visible;
btnStart.IsEnabled = false;
btnStop.IsEnabled = true;
btnClose.IsEnabled = false;
}
}
internal void UpdateStatus()
{
SetStatus(true);
_bWorking = false;
}
private void ThreadFunc()
{
//for (; ; )
//{
// // do something here
// if (_bWorking == false)
// break;
//}
Thread.Sleep(500);
this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus));
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
_bWorking = true;
SetStatus(false);
this.UpdateLayout();//this.InvalidateVisual();
try
{
Thread t = new Thread(new ThreadStart(() =>
{
ThreadFunc();
}));
t.IsBackground = true;
t.Name = "test status";
t.Start();
while (t.IsAlive)
{
// wait thread exit
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
_bWorking = false;
SetStatus(true);
}
But actually after I click button start, the UI seems frozen, and the thread exited, the UI become normal.
my VS is VS2010.
Force a WPF control to refresh?
this post is not work for me.
edit summary:
add delegate void UpdateStatusDelegate() and function UpdateStatus() to my code
// wait thread exit
The whole point of a background thread is to not wait for it by blocking your UI thread. Don't.
Instead, have the thread notify your UI when it's done.
Try to use BackgroundWorker component it might help you. For more information check the MSDN article
workable code
public delegate void UpdateStatusDelegate();
private bool _bWorking = false;
private void SetStatus(bool bEnable)
{
if (bEnable)
{
tbName.IsReadOnly = false;
barStatus.Visibility = Visibility.Hidden;
btnStart.IsEnabled = true;
btnStop.IsEnabled = false;
btnClose.IsEnabled = true;
}
else
{
tbName.IsReadOnly = true;
barStatus.Visibility = Visibility.Visible;
btnStart.IsEnabled = false;
btnStop.IsEnabled = true;
btnClose.IsEnabled = false;
}
}
internal void UpdateStatus()
{
SetStatus(true);
}
private void ThreadFunc()
{
try
{
// use Stopwatch to simulate jobs
var watch = Stopwatch.StartNew();
for (; ; )
{
var elapsedMs = watch.ElapsedMilliseconds;
if (elapsedMs > 10000 // 10 seconds
|| _bWorking == false)
{
break;
}
}
watch.Stop();
this.Dispatcher.Invoke(new UpdateStatusDelegate(UpdateStatus));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
_bWorking = false;
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
_bWorking = true;
SetStatus(false);
Thread t = new Thread(new ThreadStart(() =>
{
ThreadFunc();
}));
t.IsBackground = true;
t.Name = "test status";
t.Start();
//while (t.IsAlive)
{
// wait thread exit
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
_bWorking = false;
SetStatus(true);
}
I have an application that scans the local network for connected PC's.
I want to get the client information (IP address, MAC address, Host name...) and the connection state (download rate, upload rate), and put them in the ListView, but the problem is that this information is not constant!
How could I get this information in real time? The info in the ListView changes every time the info of the client changes?
My current code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using NetUtils;
using System.Net;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
private IPScanner _scanner;
private class HostSorterByIP : IComparer
{
public int Compare(object x, object y)
{
byte[] bytes1 = ((IPScanHostState)((ListViewItem)x).Tag).Address.GetAddressBytes();
byte[] bytes2 = ((IPScanHostState)((ListViewItem)y).Tag).Address.GetAddressBytes();
int i = bytes1.Length - 1;
for (; i > 0 && bytes1[i] == bytes2[i]; i--)
;
return bytes1[i] - bytes2[i];
}
}
public Form1()
{
InitializeComponent();
_scanner = new IPScanner((int)_spnConcurrentPings.Value, (int)_spnPingsPerScan.Value, _cbContinuousScan.Checked,
(int)_spnTimeout.Value, (int)_spnTTL.Value, _cbDontFragment.Checked, (int)_spnBufferSize.Value);
_scanner.OnAliveHostFound += new IPScanner.AliveHostFoundDelegate(_scanner_OnAliveHostFound);
_scanner.OnStartScan += new IPScanner.ScanStateChangeDelegate(_scanner_OnStartScan);
_scanner.OnStopScan += new IPScanner.ScanStateChangeDelegate(_scanner_OnStopScan);
_scanner.OnRestartScan +=new IPScanner.ScanStateChangeDelegate(_scanner_OnRestartScan);
_scanner.OnScanProgressUpdate +=new IPScanner.ScanProgressUpdateDelegate(_scanner_OnScanProgressUpdate);
_lvAliveHosts.ListViewItemSorter = new HostSorterByIP();
_cmbRangeType.SelectedIndex = 0;
}
private void _scanner_OnAliveHostFound(IPScanner scanner, IPScanHostState host)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.AliveHostFoundDelegate(_scanner_OnAliveHostFound), scanner, host);
return;
}
ListViewItem item = new ListViewItem();
item.Tag = host;
item.BackColor = Color.GreenYellow;
item.SubItems.Add(host.Address.ToString());
item.SubItems.Add("");
item.SubItems.Add("");
item.SubItems.Add("");
_lvAliveHosts.Items.Add(item);
_lvAliveHosts.Sort();
host.OnHostNameAvailable += new IPScanHostState.HostNameAvailableDelegate(host_OnHostNameAvailable);
host.OnStateChange += new IPScanHostState.StateChangeDelegate(host_OnStateChange);
if (!host.IsTesting())
{
item.ImageIndex = (int)host.QualityCategory;
item.SubItems[2].Text = host.AvgResponseTime.ToString("F02") + " ms";
item.SubItems[3].Text = ((float)(host.LossCount) / host.PingsCount).ToString("P");
item.SubItems[4].Text = host.HostName;
}
//AddLogEntry("Host [" + host.Address.ToString() + "] is alive.");
Timer newTimer = new Timer();
newTimer.Tag = item;
newTimer.Interval = 2000;
newTimer.Tick += new EventHandler(newTimer_Tick);
newTimer.Enabled = true;
}
void host_OnHostNameAvailable(IPScanHostState host)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanHostState.HostNameAvailableDelegate(host_OnHostNameAvailable), host);
return;
}
ListViewItem item = FindListViewItem(host);
if (item != null)
item.SubItems[4].Text = host.HostName;
}
private ListViewItem FindListViewItem(IPScanHostState host)
{
foreach (ListViewItem item in _lvAliveHosts.Items)
{
if (item.Tag == host)
return item;
}
return null;
}
private void host_OnStateChange(IPScanHostState host, IPScanHostState.State oldState)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanHostState.StateChangeDelegate(host_OnStateChange), host, oldState);
return;
}
if (!host.IsTesting())
{
ListViewItem item = FindListViewItem(host);
if (item != null)
{
if (host.IsAlive())
{
item.ImageIndex = (int)host.QualityCategory;
item.SubItems[2].Text = host.AvgResponseTime.ToString("F02") + " ms";
item.SubItems[3].Text = ((float)(host.LossCount) / host.PingsCount).ToString("P");
}
else
{
//AddLogEntry("Host [" + host.Address.ToString() + "] died.");
host.OnStateChange -= host_OnStateChange;
host.OnHostNameAvailable -= host_OnHostNameAvailable;
item.BackColor = Color.IndianRed;
Timer removeTimer = new Timer();
removeTimer.Tag = item;
removeTimer.Interval = 2000;
removeTimer.Tick += new EventHandler(removeTimer_Tick);
removeTimer.Enabled = true;
}
}
}
}
void newTimer_Tick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
timer.Tick -= newTimer_Tick;
ListViewItem item = (ListViewItem)timer.Tag;
item.BackColor = Color.White;
}
void removeTimer_Tick(object sender, EventArgs e)
{
Timer timer = (Timer)sender;
timer.Stop();
timer.Tick -= newTimer_Tick;
ListViewItem item = (ListViewItem)timer.Tag;
_lvAliveHosts.Items.Remove(item);
}
private void _scanner_OnStartScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnStartScan), scanner);
return;
}
foreach (ListViewItem item in _lvAliveHosts.Items)
{
((IPScanHostState)item.Tag).OnStateChange -= host_OnStateChange;
((IPScanHostState)item.Tag).OnHostNameAvailable -= host_OnHostNameAvailable;
}
_lvAliveHosts.Items.Clear();
_prgScanProgress.Value = 0;
EnableSettings(false);
}
private void EnableSettings(bool enable)
{
_cmbRangeType.Enabled = _tbRangeStart.Enabled = _tbRangeEnd.Enabled = _spnTimeout.Enabled = _spnTTL.Enabled = _spnBufferSize.Enabled = _cbDontFragment.Enabled =
_spnConcurrentPings.Enabled = _spnPingsPerScan.Enabled = _cbContinuousScan.Enabled = enable;
_btnStartStop.Text = enable ? "&Start" : "&Stop";
if (enable)
_prgScanProgress.Text = "Scanner is not running!";
}
private void _btnStartStop_Click(object sender, EventArgs e)
{
if (!_scanner.Active)
{
try
{
_scanner.Start(_cmbRangeType.SelectedIndex == 0
? new IPScanRange(IPAddress.Parse(_tbRangeStart.Text), IPAddress.Parse(_tbRangeEnd.Text))
: new IPScanRange(IPAddress.Parse(_tbRangeStart.Text), int.Parse(_tbRangeEnd.Text)));
}
catch (FormatException)
{
MessageBox.Show(this, "Cannot parse IP range or subnetmask!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
_scanner.Stop(false);
}
private void _scanner_OnStopScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnStopScan), scanner);
return;
}
EnableSettings(true);
_prgScanProgress.Value = 0;
}
void _scanner_OnRestartScan(IPScanner scanner)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanStateChangeDelegate(_scanner_OnRestartScan), scanner);
return;
}
_prgScanProgress.Value = 0;
}
void _scanner_OnScanProgressUpdate(IPScanner scanner, IPAddress currentAddress, ulong progress, ulong total)
{
if (InvokeRequired)
{
BeginInvoke(new IPScanner.ScanProgressUpdateDelegate(_scanner_OnScanProgressUpdate), scanner, currentAddress, progress, total);
return;
}
int prog = (int)((100 * progress) / total);
_prgScanProgress.Value = prog;
_prgScanProgress.Text = prog.ToString() + "%" + " [" + currentAddress.ToString() + "]";
}
private void _cmbRangeType_SelectedIndexChanged(object sender, EventArgs e)
{
if (_cmbRangeType.SelectedIndex == 0)
{
_lRangeSep.Text = "-";
_lRangeEnd.Text = "Range &End:";
_tbRangeEnd.Size = new Size(130, _tbRangeEnd.Size.Height);
}
else
{
_lRangeSep.Text = "/";
_lRangeEnd.Text = "Subnet &Mask:";
_tbRangeEnd.Size = new Size(32, _tbRangeEnd.Size.Height);
}
}
//private void _lvAliveHosts_DoubleClick(object sender, EventArgs e) { _btnAddHost_Click(sender, e); }
private void IPScanForm_FormClosing(object sender, FormClosingEventArgs e) { _scanner.Stop(true); }
private ListViewItem.ListViewSubItem _activeTooltipSubitem = null;
private static string[] QualityCategoryNames = { "Very Poor", "Poor", "Fair", "Good", "Very Good", "Excellent", "Perfect" };
private void _lvAliveHosts_MouseMove(object sender, MouseEventArgs e)
{
ListViewItem item = _lvAliveHosts.HitTest(e.Location).Item;
if (item != null)
{
ListViewItem.ListViewSubItem subitem = _lvAliveHosts.HitTest(e.Location).SubItem;
if (subitem != null && item.SubItems.IndexOf(subitem) == 0)
{
if (_activeTooltipSubitem != subitem)
{
_ttQuality.Show("Quality: " + QualityCategoryNames[item.ImageIndex], _lvAliveHosts, item.SubItems[1].Bounds.X, subitem.Bounds.Y);
_activeTooltipSubitem = subitem;
}
return;
}
}
_activeTooltipSubitem = null;
_ttQuality.Hide(_lvAliveHosts);
}
}
}
I would create the list of clients and show them in the listview.
Than, in a background thread, every X seconds, poll all of the current clients.
Next , compare the list of updated clients to a list of clients from last update.
What remain to do is to add any new client to the list, and remove any client which no longer exists.
Pay attention to the context, use InvokeRequired() to get access to the UI control from the background thread.
EDIT:
here is how to run a background thread:
static void Main(string[] args)
{
Thread worker = new Thread(DoBackgroundWork);
}
public static void DoBackgroundWork()
{
while (true)
{
//Sleep 10 seconds
Thread.Sleep(10000);
//Do some work and than post to the control using Invoke()
}
}