how to make that ongoing actions WebBrowserDocumentCompleted worked in a separate thread. And so it does not affect the main form (not hang the entire application)
Form1
private void bStart_Click(object sender, EventArgs e)
{
wb.Navigate("http://www.moswar.ru");
}
Form2
public void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
wb = sender as WebBrowser;
ThreadPool.QueueUserWorkItem(new WaitCallback((object unused) =>
{
if (wb.Document.GetElementById("login-email") != null)
{
wb.Document.GetElementById("login-email").InnerText = "myemail#blah.pe";
wb.Document.GetElementById("login-password").InnerText = "MyPassword";
GetElementsByClassName(new string[] { "button luxury" })[0].InvokeMember("click");
}
if (e.Url.AbsoluteUri == "http://www.moswar.ru/player/" || e.Url.AbsoluteUri == "http://www.moswar.ru/player/#login")
{
wb.Navigate("http://www.moswar.ru/metro/");
}
}));
//and so on .....
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
ThreadPool.QueueUserWorkItem(delegate
{
MessageBox.Show("hi");
}
}
Related
I want to know the the task status runnning in A button event from the other button click.
Like this.
private void button1_Click(object sender, EventArgs e)
{
Task.Run(()=>{
//The method to take long time
//For example
Thread.Sleep(5000)
;});
}
private coid button2_Click(object sender, EventArgs e)
{
//until 5000ms
//the method to know the above task status (Runnning....)
//after 5000ms
//the method to know the above task status (Conpleted....)
}
It's not entirely clear what you're trying to achieve, but if you want to check the status of the task, you can get its reference when calling Task.Run()
private Task _task;
private void button1_Click(object sender, EventArgs e)
{
_task = Task.Run(() => Thread.Sleep(5000));
}
private void button2_Click(object sender, EventArgs e)
{
if (_task?.Status == TaskStatus.RanToCompletion)
//do something
}
The answer is as vague as the question, so if you could give me a bit more details, I could come up with a better more tailored answer.
Again, it's very unclear what you're looking for here...but this is an expanded version of Faylit's example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Task T = null;
private void Form1_Load(object sender, EventArgs e)
{
updateStatus();
}
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
await (T = Task.Run(() =>
{
updateStatus();
System.Threading.Thread.Sleep(5000);
}));
button1.Enabled = true;
updateStatus();
}
private void button2_Click(object sender, EventArgs e)
{
updateStatus();
}
private void updateStatus()
{
if (label1.InvokeRequired)
{
label1.Invoke((MethodInvoker)delegate
{
updateStatus();
});
}
else
{
if (T == null)
{
label1.Text = "Task not started.";
}
else if (!T.IsCompleted)
{
label1.Text = "Task running...";
}
else
{
label1.Text = "Task completed.";
}
}
}
}
It might give you some more ideas.
When ran the code which is GUI based and it actually opens a webcamera feed and saves frame every 5s, after a random running time(it could be 5 min or 20 min) there is an exception occuring ''Object in use by another process'' possibly related to the saving of the current frame. Any ideas what causes the problem and what code modifications should be done?
public partial class Form1 : Form
{
private FilterInfoCollection CaptureDevices;
private VideoCaptureDevice videoSource;
bool blncapturing;
public Form1()
{
InitializeComponent();
timer1.Enabled = false;
timer1.Interval = 5000;
blncapturing = false;
}
private void button1_Click(object sender, EventArgs e)
{
videoSource = new VideoCaptureDevice(CaptureDevices[comboBox1.SelectedIndex].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(VideoSource_NewFrame);
videoSource.Start();
timer1.Enabled = true;
}
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void Form1_Load_1(object sender, EventArgs e)
{
CaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevices)
{
comboBox1.Items.Add(Device.Name);
}
comboBox1.SelectedIndex = 0;
videoSource = new VideoCaptureDevice();
}
private void button2_Click(object sender, EventArgs e)
{
videoSource.Stop();
pictureBox1.Image = null;
pictureBox1.Invalidate();
pictureBox2.Image = null;
pictureBox2.Invalidate();
}
private void button3_Click(object sender, EventArgs e)
{
Capturing();
}
private void button4_Click(object sender, EventArgs e)
{
if (videoSource.IsRunning == true)
{
videoSource.Stop();
}
Application.Exit(null);
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
Capturing();
timer1.Start();
}
private void Capturing()
{
try
{
if (blncapturing == false)
{
blncapturing = true;
pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
string strGrabFileName = String.Format("C:\\Users\\echristo\\Desktop\\trial\\Snapshot_{0:yyyyMMdd_hhmmss.fff}.bmp", DateTime.Now);
pictureBox2.Image.Save(strGrabFileName, System.Drawing.Imaging.ImageFormat.Jpeg) ;
blncapturing = false;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
If you access objects from different threads you need a lock.
Also use invoke when you access a control from a different thread.
private readonly object myLock = new object();
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
lock (myLock) {
this.Invoke((Action)(() => {
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
// you can try with timer1 inside the lock
lock (myLock) {
// you don't need invoke here, because the winforms timer runs on the main thread.
Capturing();
}
timer1.Start();
}
Also as #TheGeneral said, dispose pictureBox2.Image after saving.
I trying to do an inteface to monitoring the Serial Port. I am using Visual forms. So, I had created a combobox to select the PortCOM, a TextBox to send the data to Serial Port and a TextBoxReceber to receive the Serial Data. I trying print the data received in the TextBoxReceber, I'm using the AppendText but I haven't sucess. Anybody can help me?
My Form1.cs is:
namespace ConsoleESP
{
public partial class Form1 : Form
{
string RxString = "";
public Form1()
{
InitializeComponent();
timerCOM.Enabled = true;
atualizaCOMs();
}
private void atualizaCOMs()
{
int i = 0;
bool quantDif = false;
if (comboBox1.Items.Count == SerialPort.GetPortNames().Length)
{
foreach (string s in SerialPort.GetPortNames())
{
if (comboBox1.Items[i++].Equals(s) == false)
{
quantDif = true;
}
}
}
else quantDif = true;
if (quantDif == false) return;
comboBox1.Items.Clear();
foreach(string s in SerialPort.GetPortNames())
{
comboBox1.Items.Add(s);
}
comboBox1.SelectedIndex = 0;
}
private void timerCOM_Tick(object sender, EventArgs e)
{
atualizaCOMs();
}
private void btConnect_Click(object sender, EventArgs e)
{
if(serialPort1.IsOpen == false)
{
try
{
serialPort1.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString();
serialPort1.Open();
}
catch
{
return;
}
if (serialPort1.IsOpen)
{
btConnect.Text = "Desconectar";
comboBox1.Enabled = false;
}
}
else
{
try
{
serialPort1.Close();
comboBox1.Enabled = true;
btConnect.Text = "Conectar";
}
catch
{
return;
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (serialPort1.IsOpen == true) serialPort1.Close();
}
private void btEnviar_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen == true)
serialPort1.Write(textBoxEnviar.Text);
}
private delegate void RefreshTextBox();
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadExisting();
this.Invoke(new EventHandler(TrataDadoRecebido));
}
private void TrataDadoRecebido(object sender, EventArgs e)
{
textBoxReceber.AppendText(RxString);
}
}
}
i am calling an asmx service from my windows form application in a background worker. i want to be able to cancel/stop the call once a button is pressed.
i am currently performing the following:
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
GlobalVariables.worker = sender as BackgroundWorker;
try
{
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
e.Result = CallServer(ServerName, ActionName); // call on a web method in the referenced service
}
}
catch (Exception ee)
{
GlobalFunctions.ShowError(ee);
}
}
private void button1_Click(object sender, EventArgs e) //button to cancel the call
{
if (GlobalVariables.worker.IsBusy == true)
{
//GlobalVariables.worker.thre;
GlobalVariables.worker.CancelAsync();
GlobalVariables.worker.Dispose();
}
//GlobalVariables.worker.CancelAsync();
Form1.f.Enabled = true;
Form1.f.progressBar1.Text = "Done!";
Form1.f.progressBar1.Visible = false;
Form1.f.textBox1.Visible = true;
Close();
}
the following doesnt seem to work because when i press on cancel, the web method called in the service reference is not stopped and still returns data
You can make client react immediately to the Abort button by using a Task and a CancellationToken. The client will do its best to abort the call, but the server will continue execution of the call unless it does something special about that.
Here is the code of the client side:
public partial class Form1 : Form
{
private CancellationTokenSource _cancellationTokenSource;
private WebService1SoapClient _client;
public Form1()
{
InitializeComponent();
btnAbort.Enabled = false;
}
private void btnCall_Click(object sender, EventArgs e)
{
btnCall.Enabled = false;
btnAbort.Enabled = true;
lblStatus.Text = "CALLING SERVER...";
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource.Token.Register(() => backgroundWorker1.CancelAsync());
backgroundWorker1.RunWorkerAsync();
}
private void btnAbort_Click(object sender, EventArgs e)
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
try
{
_client = new WebService1SoapClient();
var call = CallServerAsync("ServerName", "ActionName");
call.Wait(_cancellationTokenSource.Token);
e.Result = call.Result;
}
catch (TaskCanceledException)
{
e.Cancel = true;
_client.Abort();
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnCall.Enabled = true;
btnAbort.Enabled = false;
lblStatus.Text = (e.Error != null ? "CALL FAILED: " + e.Error.Message : "CALL COMPLETED!");
}
private async Task<string> CallServerAsync(string serverName, string actionName)
{
var response = await _client.HelloWorldAsync();
return response.Body.HelloWorldResult;
}
}
thanks to #felix-b answer , i did the following:
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
GlobalVariables.worker = sender as BackgroundWorker;
try
{
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
Object callResponse = CallServer(ServerName, ActionName);
if (GlobalVariables.worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
e.Result = callResponse;
}
}
}
catch (Exception ee)
{
e.Cancel = true;
if (ee.GetType().IsAssignableFrom(typeof(System.ServiceModel.CommunicationObjectAbortedException)))
{
MessageBox.Show("The Request Was Cancelled");
}
else
{
GlobalFunctions.ShowError(ee);
}
}
}
public void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{}
else
{
//continue
}
}
private void button1_Click(object sender, EventArgs e)
{
if (GlobalVariables.worker.IsBusy == true)
{
server.abort(); //service reference
GlobalVariables.worker.CancelAsync();
GlobalVariables.worker.Dispose();
}
}
I am creating a To Do List using Windows Forms.
This is what I have so far.
The code for this form is as follows
namespace To_Do_List
{
public partial class To_Do_List : Form
{
public To_Do_List()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e) //this is the exit button on the toolstrip
{
Application.Exit(); //exits the program when the Exit button is clicked in dropdown menu
}
private void button4_Click(object sender, EventArgs e)//This creates the button to open the about form
{
AboutMyProgram aboutForm = new AboutMyProgram();
aboutForm.ShowDialog(); //opens about form
}
private void button3_Click(object sender, EventArgs e) //This creates the button to open the form which ammends tasks
{
AmmendItem CreateForm = new AmmendItem(this);
CreateForm.Show();
}
private void button1_Click(object sender, EventArgs e) // This creates the button to open the form which creates new tasks
{
AddItem CreateForm = new AddItem(this);
CreateForm.Show();
}
public void listView1_SelectedIndexChanged_1(object sender, EventArgs e) // This creates the table
{
}
private void button2_Click(object sender, EventArgs e) //This Allows the user to delete entries
{
if (listView1.SelectedItems != null)
{
var confirmation = MessageBox.Show(
"Are you sure you want to delete this?",
"WARNING", MessageBoxButtons.YesNo, MessageBoxIcon.Question
);
if (confirmation == DialogResult.Yes)
{
for (int i = listView1.Items.Count - 1; i >= 0; i--)
{
if (listView1.Items[i].Selected)
{
listView1.Items[i].Remove();
i--;
}
}
}
}
}
}
}
To add a task, the form looks like this
And again, the code is as follows
namespace To_Do_List
{
public partial class AddItem : Form
{
To_Do_List home;
public AddItem(To_Do_List parent)
{
InitializeComponent();
home = parent;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label1_Click_1(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
private void openListToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void sortByDateToolStripMenuItem_Click(object sender, EventArgs e)
{
}
public void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
}
public void textBox1_TextChanged(object sender, EventArgs e)//Title Box
{
}
public void /*Description of Task*/richTextBox1_TextChanged(object sender, EventArgs e)
{
}
public void /*Priority Box*/comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close(); //causes the window to close but keeps the application running
}
private void aboutToDoListToolStripMenuItem_Click(object sender, EventArgs e)
{
AboutMyProgram aboutForm = new AboutMyProgram();
aboutForm.ShowDialog(); //opens about form displaying copyright information
}
public void button1_Click(object sender, EventArgs e) //create task button
{
ListViewItem item1 = new ListViewItem(Title.Text);
item1.SubItems.Add(Description.Text);
item1.SubItems.Add(Priority.Text);
item1.SubItems.Add(Date.Text);
string value = "";
bool isChecked = Completed.Checked;
if (isChecked)
item1.SubItems.Add(Completed.Text);
else
value = null;
home.listView1.Items.Add(item1);
this.Close();
}
private void Date_ValueChanged(object sender, EventArgs e)
{
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e) //Closes the window
{
this.Close();
}
}
}
The Amend form is exactly the same as the New Task form. How would I go about being able to select a record, pressing the amend button and actually changing?
I'm pretty stumped.
Also, this isn't really part of this question but I'll ask it just in case someone knows.
How would I go about being able to actually save these records so that they are there when I open the application back up again?
Thank you very much for reading, I know that I have just dumped everything but I'm really new to Windows Forms so I didn't want to accidentally miss something important out.
Edit
Am I on the right road with something like this?
public void button1_Click(object sender, EventArgs e)
{
To_Do_List editform = new To_Do_List(Title.Text);
editform.Description.Text = listView1.SelectedItems[0].SubItems[0].Text;
Still can't get it to work :/
This code for popup window.
public partial class frmToDoDetails : Form
{
public string TaskTitle { get; set; }
public string Description { get; set; }
public bool EditMode { get; set; }
public frmToDoDetails()
{
InitializeComponent();
}
private void btnSave_Click(object sender, EventArgs e)
{
TaskTitle = txtTitle.Text;
Description = txtDesc.Text;
this.DialogResult = System.Windows.Forms.DialogResult.OK;
}
private void frmToDoDetails_Load(object sender, EventArgs e)
{
if (EditMode)
{
txtTitle.Text = TaskTitle;
txtDesc.Text = Description;
}
else {
txtTitle.Text = string.Empty;
txtDesc.Text = string.Empty;
}
txtTitle.Focus();
}
}
And this for list
public partial class frmToDo : Form
{
public frmToDo()
{
InitializeComponent();
}
private void btnNew_Click(object sender, EventArgs e)
{
frmToDoDetails frm = new frmToDoDetails();
if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string[] arr = new string[2];
ListViewItem itm;
arr[0] = frm.TaskTitle;
arr[1] = frm.Description;
itm = new ListViewItem(arr);
listView1.Items.Add(itm);
}
}
private void frmToDo_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
//Add column header
listView1.Columns.Add("Title", 100);
listView1.Columns.Add("Desc", 70);
}
private void listView1_DoubleClick(object sender, EventArgs e)
{
ListViewItem currentItem= listView1.SelectedItems[0];
frmToDoDetails frm = new frmToDoDetails();
frm.TaskTitle = currentItem.SubItems[0].Text;
frm.Description = currentItem.SubItems[1].Text;
frm.EditMode = true;
if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
currentItem.SubItems[0].Text=frm.TaskTitle;
currentItem.SubItems[1].Text=frm.Description;
}
}
}
I am not added your complete fields(priority, date,etc..).
I hope it will help you.