C# Background worker not completing - c#

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;

Related

Using GetActiveTcpConnections to continuously check for new IP

I"m new to C# and am looking to see if the way I'm using this code to check for a new connection in a background worker is safe and or a better why to do it. My end goal is to run this as a service but, I'm using the background worker as a way to get real-time updates for testing. The code works but I don't know if its safe/stable or the best way to do it?
Any help would be appreciated.
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.RunWorkerAsync(2000);
MessageBox.Show("Started backgroung worker");
}
private void button2_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
MessageBox.Show("Stopped backgroung worker");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker helperBW = sender as BackgroundWorker;
e.Result = BackgroundProcessLogicMethod(helperBW, arg);
if (helperBW.CancellationPending)
{
e.Cancel = true;
}
}
private int BackgroundProcessLogicMethod(BackgroundWorker bw, int a)
{
while (true)
{
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] connections = properties.GetActiveTcpConnections();
foreach (TcpConnectionInformation c in connections)
{
if (c.RemoteEndPoint.ToString() == "192.168.4.14:443")
richTextBox1.Invoke(new Action( () => richTextBox1.AppendText(c.RemoteEndPoint.ToString() + "\n\r") ) );
}
}
}
Consider throttling the while(true)... loop but other than that you seem to be doing the right things in your post. This kind of thing shows up a lot in my own production code so I wanted to offer the tried-and-true approach that works for me. It's just another perspective, however.
Your code references RichTextBox which makes me infer that a WinForms example will fly here, but the general approach is valid regardless of platform anyway.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
checkBoxRun.CheckedChanged += onRunChanged;
}
CancellationTokenSource _cts = null;
private async void onRunChanged(object sender, EventArgs e)
{
if (checkBoxRun.Checked)
{
_cts = new CancellationTokenSource();
while (checkBoxRun.Checked)
{
richTextBox1.AppendTextOnUIThread(DateTime.Now.ToString());
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] connections = properties.GetActiveTcpConnections();
foreach (TcpConnectionInformation c in connections)
{
var endpoint = c.RemoteEndPoint.ToString();
switch (endpoint)
{
case "192.168.4.14:443":
richTextBox1.AppendTextOnUIThread(endpoint, color: Color.Red);
break;
case "127.0.0.1:49813":
richTextBox1.AppendTextOnUIThread(endpoint, color: Color.Blue);
break;
case "127.0.0.1:55846":
richTextBox1.AppendTextOnUIThread(endpoint, color: Color.Green);
break;
default:
continue;
}
}
richTextBox1.AppendTextOnUIThread();
// Throttle the polling to a reasonable repeat rate.
var task = Task.Delay(TimeSpan.FromSeconds(1), _cts.Token);
try{ await task; } catch (TaskCanceledException){ Debug.WriteLine("Cancelled"); }
}
}
else _cts.Cancel();
}
}
With the following extension for RichTextBox:
static class Extensions
{
public static void AppendTextOnUIThread(this RichTextBox #this, string text = "", bool newLine = true, Color? color = null)
{
if (!#this.Disposing)
{
if (newLine) text = $"{text}{Environment.NewLine}";
#this.BeginInvoke(new Action(() =>
{
if (color == null)
{
#this.AppendText(text);
}
else
{
var colorB4 = #this.ForeColor;
#this.SelectionColor = (Color)color;
#this.AppendText(text);
#this.SelectionColor = colorB4;
}
}));
}
}
}

Sleep Thread With IF condition in C#

In my C# windows form, I want to set notification label with loop and thread before fill the data into data grid view . for that I try to use below method and thread.
My Thread is
public void Run()
{
System.Windows.Forms.MessageBox.Show("this is System Thread");
m = new Dashboard();
string text = "";
Int32 a = 0;
do
{
Thread.Sleep(1000);
notiCount++;
/*Notifications ne = new Notifications(m.loadNotification);
ne.Invoke(text);*/
//Thread.Sleep(1000);
}
while (notiCount <= 10) ;
}
My method is
private void loadINtransfer(string status)
{
Int32 x = 0;
string text="";
SystemThreadings s = new SystemThreadings();
Thread t = new Thread(s.Run);
t.Start();
Thread.Sleep(100);
do
{
if (s.notiCount == 0)
{
text = "Request Data";
Thread.Sleep(1000);
this.loadNotification(text);
// MessageBox.Show("request");
}
else if (s.notiCount == 3)
{
text = "Fetching Data";
Thread.Sleep(1000);
//MessageBox.Show("request");
this.loadNotification(text);
}
else if (s.notiCount == 6)
{
text = "Loading Data";
Thread.Sleep(1000);
this.loadNotification(text);
//MessageBox.Show("loading");
}
else if (s.notiCount == 9)
{
text = "Done";
Thread.Sleep(1000);
this.loadNotification(text);
//MessageBox.Show("done");
}
//Thread.Sleep(200);
}
while (s.notiCount != 10);
//Thread.Sleep(5000);
MessageBox.Show("attach");
dt = dl.loadTransfer(status);
dgvDashboard.AutoGenerateColumns = false;
dgvDashboard.DataSource = dt;
}
but it only show Done part. other if parts are passing but not show. And I want to wait some time the all parts before load data to grid view. how can I do this. Please help Me.
As I alluded to in the comments, this is pretty well a poster-child use case for BackgroundWorker. I created a new Windows Forms application, added a button and a label (I didn't bother to rename them), and then double-clicked the button to add an event handler. After adding the BackgroundWorker code, this is what Form1.cs ended up looking like:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var bw = new BackgroundWorker();
bw.DoWork += Bw_DoWork;
bw.WorkerReportsProgress = true;
bw.ProgressChanged += Bw_ProgressChanged;
bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
bw.RunWorkerAsync();
}
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("attach");
//dt = dl.loadTransfer(status);
//dgvDashboard.AutoGenerateColumns = false;
//dgvDashboard.DataSource = dt;
}
private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 0)
{
label1.Text = "Request Data";
}
else if (e.ProgressPercentage == 3)
{
label1.Text = "Fetching Data";
}
else if (e.ProgressPercentage == 6)
{
label1.Text = "Loading Data";
}
else if (e.ProgressPercentage == 9)
{
label1.Text = "Done";
}
}
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
int notiCount = 0;
do
{
Thread.Sleep(1000);
notiCount++;
worker.ReportProgress(notiCount);
}
while (notiCount <= 10);
}
}
}
Notice that we're not having to sleep or wait on the UI thread. When progress has been made, we're notified and can access the UI to update it. And when the work is complete, we again get notified.
The only Thread.Sleep we have is within the background worker, and I assume there is standing for actual useful work being done.
You absolutely should not have any Thread.Sleep calls in any constrained context such as the UI thread, where there aren't likely to be any other threads available to service other uses which may want to use your thread whilst you're just blocking it. Even Sleeping a threadpool thread is acting as a bad "team player" in modern multi-threaded applications.

Cancelling task in C#

I have a Form with two buttons (Start , Stop).
When I press Start Button a Task is initialized and a function is called that keeps running until Stop button is pressed.
But When I press Stop button Form freezes. why?
I have copied snippet from StackOverflow but it still freezes Form.
So tell me how to Cancel Task properly?
public partial class Form1 : Form
{
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private Task _task;
public Form1()
{
InitializeComponent();
}
//Funtion that runs when Task is initialized.
private void EventLoop(CancellationToken token)
{
//Code here..
while (!token.IsCancellationRequested)
{
//Code here..
}
if (token.IsCancellationRequested)
{
MessageBox.Show("Operation Complete..!!");
}
}
//Function for Start Button.
private void Start_Click(object sender, EventArgs e)
{
_task = Task.Factory.StartNew(() => EventLoop(_cts.Token), _cts.Token);
}
//Function for Stop button.
private void Stop_Click(object sender, EventArgs e)
{
_cts.Cancel();
}
}
Similar Example from MSDN:
var compute = Task.Factory.StartNew(() =>
{
return SumRootN(j);
}, tokenSource.Token);`
Form After Stop button is pressed.
token.IsCancellationRequested is true .
Full EventLoop() Function.
private void EventLoop(CancellationToken token)
{
SerialPort sp = new SerialPort();
string text, batch, part, courseName;
text = batch = part = courseName = "";
int courseId = 0;
this.Invoke((MethodInvoker)delegate()
{
text = portCB.SelectedItem.ToString();
batch = comboBox2.SelectedItem.ToString();
part = comboBox3.SelectedItem.ToString();
courseName = comboBox1.SelectedItem.ToString();
progressBar1.Value = 20;
using (Model1 db = new Model1())
{
courseId = db.Courses.Where(c => c.Course_name.ToUpper() == courseName.ToUpper()).Select(c => c.Course_Id).Single();
}
});
sp.PortName = text;
sp.BaudRate = 9600;
sp.Open();
while (!token.IsCancellationRequested)
{
text = sp.ReadLine();
if (text.Contains("Found ID #"))
{
this.Invoke((MethodInvoker)delegate()
{
textBox2.Clear();
textBox2.Text = "Getting Registation ID.\n";
progressBar1.Value = 60;
});
string splitText = text.Split('#')[1];
int end = splitText.IndexOf(' ');
int id = int.Parse(splitText.Substring(0, end));
using (Model1 db = new Model1())
{
var result = db.Students.Where(s => s.Reg_Id == id && s.Batch == batch && s.Class == part).Select(s => s).SingleOrDefault();
if (result != null)
{
Attendance a = new Attendance();
a.Course_Id = courseId;
a.Student_Id = id;
a.Status = "P";
a.Date = DateTime.Today.Date;
a.Batch = batch;
a.Part = part;
db.Attendances.Add(a);
string message = "";
if (db.SaveChanges() != 0)
{
message = "Attendance Uploaded..!!\n";
}
else
{
message = "Attendance Not Uploaded ..!!\n";
}
this.Invoke((MethodInvoker)delegate()
{
progressBar1.Value = 100;
textBox2.AppendText(message);
});
}
else
{
this.BeginInvoke((MethodInvoker)delegate()
{
textBox2.AppendText("Student Does not belong to Specified Batch Or Part..\n");
});
}
}
}
else
{
this.Invoke((MethodInvoker)delegate()
{
textBox2.AppendText("No Match Found..!! \n");
});
}
this.Invoke((MethodInvoker)delegate()
{
textBox1.AppendText(text + "\n");
});
}
sp.Close();
// This exception will be handled by the Task
// and will not cause the program to crash
if (token.IsCancellationRequested)
{
//MessageBox.Show("Operation Comptele..!!");
}
}
You call MessageBox.Show("Operation Complete..!!"); in the progress of cancellation. This is highly not recommended, not talking about that you are calling an UI operation from other than the UI thread.
Comment the MessageBox.Show("Operation Complete..!!"); line out
* Edit *
Question author's comment on his original question, found the mistake, which line was removed from the post. Here are my conclusion:
Always try to isolate an issue, and reproduce in its purest form. During that process you will probably diagnose and find the issues itself :-).
So if the code with issue is long to post, it is definitely not the way just deleting lines then post it. The way is deleting lines and see if the issue exist, with other words: Isolating the issue in its purest reproducable form
please use async call on your task
private async void Start_Click(object sender, EventArgs e)
{
_task = Task.Factory.StartNew(() => EventLoop(_cts.Token), _cts.Token);
await task;
}

c# prevent screen capture of UserControl

The execs at my company would like a particular custom control of our ui to make a best-effort at preventing screen capture. I implemented a slick solution using SetWindowDisplayAffinity and DWMEnableComposition at the top Window level of our application to prevent screen capture of the entire app but the previously mentioned execs weren't happy with that. They want only the particular UserControl to prevent screen capture, not the entire app.
The custom control is a .NET 2.0 Windows.Forms.UserControl wrapped in a 4.5 WPF WindowsFormsHost contained by a 4.5 WPF Window control.
Before I tell the execs where to go, I want to be certain there isn't a reasonable way to implement this.
So, my question is: How do I implement screen capture prevention of a .NET 2.0 UserControl?
Thanks
i had an idea:
the user click "PrintScreen", a capture from my program is copy to ClipBoard.
So, all what i need it: to catch cliboard an check if he contains an image.
if yes: i delete the image from clipboard.
the code:
//definition a timer
public static Timer getImageTimer = new Timer();
[STAThread]
static void Main()
{
getImageTimer.Interval = 500;
getImageTimer.Tick += GetImageTimer_Tick;
getImageTimer.Start();
......
}
private static void GetImageTimer_Tick(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())//if clipboard contains an image
Clipboard.Clear();//delete
}
*but it avoid any time program is running. (you need to know if your program is foreground, and then check clipboard);
You might be able to capture the key stroke.
Below is a method I used for that, but it had limited success:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessCmdKey(ref msg, keyData);
}
}
protected override bool ProcessKeyEventArgs(ref Message msg) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessKeyEventArgs(ref msg);
}
}
Returning "True" was supposed to tell the system that the PrintScreen routine was handled, but it often still found the data on the clipboard.
What I did instead, as you can see from the call to m_parent.ScreenCapture, was to save the capture to a file, then display it in my own custom image viewer.
If it helps, here is the wrapper I created for the custom image viewer in m_parent.ScreenCapture:
public bool ScreenCapture(ref Message msg) {
var WParam = (Keys)msg.WParam;
if ((WParam == Keys.PrintScreen) || (WParam == (Keys.PrintScreen & Keys.Alt))) {
ScreenCapture(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
msg = new Message(); // erases the data
return true;
}
return false;
}
public void ScreenCapture(string initialDirectory) {
this.Refresh();
var rect = new Rectangle(Location.X, Location.Y, Size.Width, Size.Height);
var imgFile = Global.ScreenCapture(rect);
//string fullName = null;
string filename = null;
string extension = null;
if ((imgFile != null) && imgFile.Exists) {
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
} else {
using (var worker = new BackgroundWorker()) {
worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
Thread.Sleep(300);
var bmp = new Bitmap(rect.Width, rect.Height);
using (var g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(Location, Point.Empty, rect.Size); // WinForm Only
}
e.Result = bmp;
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) {
var err = e.Error;
while (err.InnerException != null) {
err = err.InnerException;
}
MessageBox.Show(err.Message, "Screen Capture", MessageBoxButtons.OK, MessageBoxIcon.Stop);
} else if (e.Cancelled) {
} else if (e.Result != null) {
if (e.Result is Bitmap) {
var bitmap = (Bitmap)e.Result;
imgFile = new FileInfo(Global.GetUniqueFilenameWithPath(m_screenShotPath, "Screenshot", ".jpg"));
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
bitmap.Save(imgFile.FullName, ImageFormat.Jpeg);
}
}
};
worker.RunWorkerAsync();
}
}
if ((imgFile != null) && imgFile.Exists && !String.IsNullOrEmpty(filename) && !String.IsNullOrEmpty(extension)) {
bool ok = false;
using (SaveFileDialog dlg = new SaveFileDialog()) {
dlg.Title = "ACP Image Capture: Image Name, File Format, and Destination";
dlg.FileName = filename;
dlg.InitialDirectory = m_screenShotPath;
dlg.DefaultExt = extension;
dlg.AddExtension = true;
dlg.Filter = "PNG Image|*.png|Jpeg Image (JPG)|*.jpg|GIF Image (GIF)|*.gif|Bitmap (BMP)|*.bmp" +
"|EWM Image|*.emf|TIFF Image|*.tif|Windows Metafile (WMF)|*.wmf|Exchangable image file|*.exif";
dlg.FilterIndex = 0;
if (dlg.ShowDialog(this) == DialogResult.OK) {
imgFile = imgFile.CopyTo(dlg.FileName, true);
m_screenShotPath = imgFile.DirectoryName;
ImageFormat fmtStyle;
switch (dlg.FilterIndex) {
case 2: fmtStyle = ImageFormat.Jpeg; break;
case 3: fmtStyle = ImageFormat.Gif; break;
case 4: fmtStyle = ImageFormat.Bmp; break;
case 5: fmtStyle = ImageFormat.Emf; break;
case 6: fmtStyle = ImageFormat.Tiff; break;
case 7: fmtStyle = ImageFormat.Wmf; break;
case 8: fmtStyle = ImageFormat.Exif; break;
default: fmtStyle = ImageFormat.Png; break;
}
ok = true;
}
}
if (ok) {
string command = string.Format(#"{0}", imgFile.FullName);
try { // try default image viewer
var psi = new ProcessStartInfo(command);
Process.Start(psi);
} catch (Exception) {
try { // try IE
ProcessStartInfo psi = new ProcessStartInfo("iexplore.exe", command);
Process.Start(psi);
} catch (Exception) { }
}
}
}
}
I wrote that years ago, and I don't work there now. The source code is still in my Cloud drive so that I can leverage skills I learned once (and forgot).
That code isn't meant to get you completely done, but just to show you a way of doing it. If you need any help with something, let me know.
Not a silver bullet, but could form part of a strategy...
If you were worried about the windows snipping tool or other known snipping tools, you could subscribe to Windows events to capture a notification of when SnippingTool.exe was launched and then hide your application until it was closed:
var applicationStartWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
applicationStartWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() => this.Visibility = Visibility.Hidden);
}
};
applicationStartWatcher.Start();
var applicationCloseWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"));
applicationCloseWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() =>
{
this.Visibility = Visibility.Visible;
this.Activate();
});
}
};
applicationCloseWatcher.Start();
You will probably need to be running as an administrator for this code to work.
ManagementEventWatcher is in the System.Management assembly.
This coupled with some strategy for handling the print screen key: for example something like this may at least make it difficult to screen capture.

how to release thread is required in multiple thread?

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

Categories

Resources