In socket programming that we wait for data receive, i show a dialog that with show method(i do not show it with show dialog method because event is not occured.)
Psudo code:
buttonClick()
{
socket.Send(array byte)
waitingForm.Show();
}
recieveCompletedEventHandler()
{
WaitingForm.Close();
}
It is ok, but user can access the form controls and because the waiting form is not modal.i just want a sample code that when i send bytes and all data received and event occur and the waiting form close. And of course the waiting form be modal when data does not receive completely.
Thanks #Ofir Winegarten for answer
i create a sample and put the code here for others
public partial class Form1 : Form
{
delegate void funDel();
private waiting waitForm;
private event funDel funEvent;
public Form1()
{
InitializeComponent();
funEvent += Form1_funEvent;
}
private void Form1_funEvent()
{
waitForm.Close();
}
private void buttonStart_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
if (InvokeRequired) // Line #1
{
this.Invoke(new MethodInvoker(() => button1.Text = "Proccessing"));
}
else
{
button1.Text = "Proccessing";
}
});
waitForm = new waiting();
timer1.Start();
waitForm.ShowDialog();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
funEvent();
}
}
Related
I have a singletone form that can be opened from a ribbon button or that will check every minute whether it should be open after passing a few conditional checks.
When opening the form from the ribbon button, it works correctly every time.
When opening on the timer, the form does not get rendered correctly, any place a control should be is just displayed as a white rectangle. Screenshots below.
ThisAddIn.cs
using Timer = System.Timers.Timer;
public partial class ThisAddIn
{
private Timer ticker;
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
ticker = new Timer(5 * 60 * 1000);
ticker.AutoReset = true;
ticker.Elapsed += new System.Timers.ElapsedEventHandler(checkForOverdue);
ticker.Start();
}
private void checkForOverdue(object sender, System.Timers.ElapsedEventArgs e)
{
bool overdue = false;
foreach (Reminder reminder in reminders)
{
DateTime now = DateTime.Now;
if (reminder.time <= now)
{
overdue = true;
break;
}
}
if (overdue)
{
RemindersList form = RemindersList.CreateInstance();
if (form != null)
{
form.Show();
}
}
}
}
Ribbon.cs
public partial class Ribbon
{
private void reminderListButton_Click(object sender, RibbonControlEventArgs e)
{
RemindersList form = RemindersList.CreateInstance();
if (form != null)
{
form.Show();
}
}
}
RemindersList.cs
public partial class RemindersList : Form
{
private static RemindersList _singleton;
private RemindersList()
{
InitializeComponent();
this.FormClosed += new FormClosedEventHandler(f_formClosed);
}
private static void f_formClosed(object sender, FormClosedEventArgs e)
{
_singleton = null;
}
public static RemindersList CreateInstance(List<Reminder> rs)
{
if (_singleton == null)
{
_singleton = new RemindersList(rs);
_singleton.Activate();
// Flash in taskbar if not active window
FlashWindow.Flash(_singleton);
return _singleton;
}
else
{
return null;
}
}
}
EDIT - SOLUTION
Per sa_ddam213's answer, I changed out the System.Timers.Timer for a Windows.Forms.Timer and it's now working just how I wanted.
Code changes:
ThisAddIn.cs
using Timer = System.Windows.Forms.Timer;
public partial class ThisAddIn {
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
ticker = new Timer();
ticker.Interval = 5 * 60 * 1000;
ticker.Tick += new EventHandler(checkForOverdue);
ticker.Start();
}
// Also needed to change the checkForOverdue prototype as follows:
private void checkForOverdue(object sender, EventArgs e)
}
You can't touch UI controls/elements with any other thread than the UI thread, in your case the System.Timer is running on another thread and the window will never open
Try switching to a Windows.Forms.Timer
Or invoke the call back to the UI thread.
private void checkForOverdue(object sender, System.Timers.ElapsedEventArgs e)
{
base.Invoke(new Action(() =>
{
/// all your code here
}));
}
I suspect that the timer event handler is not launched on the UI thread, which could cause all sorts of problems. I would check that first and ensure that the UI stuff is actually done on the UI thread.
I am working on C# window forms, in my application i am trying to execute procedures using c# window forms in page load event. I am trying for, while executing the procedure the form should display, after that form should close automatically. My code is like this
public partial class Form1 : Form
{
string servername = "";
string database = ""; string password = ""; string Filepath = ""; string uid = "";
string reslt = "";
public Form1()
{
InitializeComponent();
GetExelData();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Close();
}
}
But with my code window form is not displaying, it is closed when the methods are executed. can you help me.
Try this:-
private BackgroundWorker bw;
private void Form1_Load(object sender, EventArgs e)
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += BwOnDoWork;
bw.WorkerSupportsCancellation = true;
bw.RunWorkerAsync();
}
private void BwOnDoWork(object sender, DoWorkEventArgs e)
{
GetExelData();
bw.CancelAsync();
if (this.InvokeRequired)
{
this.Invoke(new EventHandler(delegate { this.Close(); }));
}
}
Move the GetExcelData() to the Form1_Load handler. (The Shown handler might be better)
This way the method will be called when the form is showing.
To close the form after the method has finished:
use an event or callback (if available)
or call the GetExcelData on a separate thread and close the form when the thread finishes
You could try moving the GetExcelData call to the load event:
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GetExelData();
this.Close();
}
Form load only occurs when the form is fully constructed. Note however that, even with my improvement, it doesn't make sense what you're trying to do exactly.
This "delay" in closing is only because the method is executed on the GUI thread (bad practice). Are you trying to display some kind of loading indicator? There are better ways for that.
Use Shown event handler.
This event will be executed after form was displayed first time(just what you need).
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
GetExelData();
}
private void Form1_Shown(object sender, EventArgs e)
{
this.Close();
}
My form is going to run some code that might take a while to execute. I would like to display a "please wait" message while the operation is running on the background.
I'd like to have that message in a form, one that I can control its visibility, and also its text, from other forms.
I'd also like it to be set to start in the Program.cs file.
My code, so far:
namespace KAN
{
public partial class prosze_czekac : Form
{
public prosze_czekac()
{
InitializeComponent();
}
private delegate void OffVisible();
public void Wylacz()
{
if (this.InvokeRequired)
this.Invoke(new OffVisible(Wylacz));
else
this.Visible = false;
}
delegate void SetTextCallback(string text);
public void ZmienTekst(string text)
{
if (this.InvokeRequired)
{
//SetTextCallback d = new SetTextCallback(this.ZmienTekst);
Invoke(new SetTextCallback(this.ZmienTekst), text);
//Invoke(d, new object[] { text });
}
else
{
this.Visible = true;
this.Text = text;
this.lblKomunikat.Text = text;
this.Update();
}
}
}
}
I do not know how to run a form, how to create an instance and as editing text. All this in any form, any thread.
Is the above code is correct and how to use it to make it properly?
How am I so ready form "please wait" I would like to turn it on now in the initial class (Program.cs). Use it in any form design.
Sample code, do not know if correct:
namespace KAN
{
static class Program
{
public static prosze_czekac PleaseWait;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread thread = new Thread(new ThreadStart(PleaseWait.Show());
PleaseWait.ZmienTekst("Please wait... Running the program");
// long operation
PleaseWait.Wylacz();
Application.Run(new main());
}
}
}
namespace KAN
{
public partial class main: Form
{
public main()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// examples of long task in another form
for (int i = 0; i < 5; i++)
{
Program.PleaseWait.ZmienTekst((i + 1).ToString());
System.Threading.Thread.Sleep(1000);
}
Program.PleaseWait.Wylacz();
}
}
}
The first time I ask a question, please bear with me.
PS
"Wylacz" is "exit" (void) and is meant to "hide" so that every time you do not initiate the form.
"prosze_czekac" is "please wait".
Use the BackgroundWorker. The following code assumes, you have a button 'button1' in your form, which executes the worker, which starts the long running task on a different thread:
BackgroundWorker _worker;
// button click starts the execution of the lung running task on another thread
private void button1_Click(object sender, EventArgs e)
{
label1.Visible = true; // show the label "please wait"
_worker.RunWorkerAsync();
}
private void Form1_Load(object sender, EventArgs e)
{
// initialize worker
_worker = new BackgroundWorker();
_worker.DoWork += new DoWorkEventHandler(worker_DoWork);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
}
// executes when long running task has finished
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// hide the label
label1.Visible = false;
}
// is called by 'RunWorkerAsync' and executes the long running task on a different thread
void worker_DoWork(object sender, DoWorkEventArgs e)
{
// long running task (just an example)
for (int i = 0; i < 1000000000; i++)
{
}
}
Hey everyone, can someone let me know what they see wrong with this code ?
it throws "Cross-thread operation not valid" exception, on
_DialogueThread.Start();
but if i remove "owner" from
_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
the exception wont be thrown but the progressDialouge will be shown then hidden right away .
now i understand why this the error is thrown if i set the progressDialouge.Owner to a parent form that was created on a different thread. but why dose the form disappears when i dont ? what am i doing wrong ?
thanks
class Sampleer : BackgroundWorker
{
private Progresser _progressDialogue;
private Thread _DialogueThread;
private Form _owner;
private bool _SampleSuccess;
public Sampleer(Form owner)
{
_owner = owner;
_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
_progressDialogue.Closed += ProgressDialogueClosed;
WorkerReportsProgress = true;
WorkerSupportsCancellation = true;
DoWork += Sampleer_DoWork;
RunWorkerCompleted += Sampleer_RunWorkerCompleted;
ProgressChanged += Sampleer_ProgressChanged;
}
private void Sampleer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//UPDATE STATUS CODE IS HERE
}
void ProgressDialogueClosed(object sender, EventArgs e)
{
CancelAsync();
Dispose();
}
void Sampleer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//FINISH PROCESS
}
void Sampleer_DoWork(object sender, DoWorkEventArgs e)
{
_DialogueThread = new Thread(_progressDialogue.Show);
_DialogueThread.Start();
//DO LONG PROCESS HERE
}
}
In your action (button click), i would create the progress dialog, and then fire off the background worker. The background worker then reports back to the dialog in the ProgressChanged event.
public partial class MainWindow : Window {
private void btnDoSomething_Click(object sender0, RoutedEventArgs e0) {
_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
_progressDialogue.Closed += ProgressDialogueClosed;
_progressDialogue.Show();
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
DoSomething();
e.Result = result;
};
worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e) {
progressDialogue.Update()
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
progressDialogue.Close()
};
worker.RunWorkerAsync(new CustomArgs() {
SomeValue = txtValue.Text,
});
}
}
There are a few mistakes in your approach. Let me point them out one by one.
You inherit BackgroundWorker. That is fine. But you create another thread inside (_DialogueThread). There is no need. DoWork() method runs in a separate thread.
You create/use/manipulate a UI element in another thread. Now, always remember. A Thread never creates a UI element. Its the other way around. A UI element creates a Thread. Progresser in your case should be creating a new Thread or using BackgroundWorker to do any background work you require.
`
Yes decyclone is right, there are many mistakes in the code and in your approach to solution.
You are inherting BackgroundWorker type but subscribing to its own events?
Instead override the methods that are responsible for raising the event in your class.
ex: Instead of subscribing to DoWork, override OnDoWork method.
I've created a sample application, in which a Form (when performing a background task) shows another Form (BackgroundWorkUINotification) and starts the background task in BackgroundWorker thread. The BackgroundWorkUINotification notifies the main form when the Form's CancelButton is clicked.
The main Form when notified, closes the notifier and cancels the background task.
Code below: BackgroundWorkUINotification Form
public partial class BackgroundWorkUINotification : Form
{
public event EventHandler CancelClicked;
public BackgroundWorkUINotification()
{
InitializeComponent();
// call code to animate progress bar..
// probably in another BackgroundWorker that reports progress..
this.cancelButton.Click += HandleCancelButtonOnClick;
}
protected virtual void OnCancelClicked()
{
if (CancelClicked != null)
this.CancelClicked(this, EventArgs.Empty);
}
private void HandleCancelButtonOnClick(Object sender, EventArgs e)
{
this.OnCancelClicked();
}
}
Main Form
public partial class Form1 : Form
{
private BackgroundWorker backgroundWorker;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.backgroundWorker = new BackgroundWorker();
this.backgroundWorker.DoWork += HandleBackgroundWorkerOnDoWork;
this.backgroundWorker.RunWorkerCompleted += HandleBackgroundWorkerOnRunWorkerCompleted;
this.backgroundWorker.WorkerSupportsCancellation = true;
}
private void HandleDataRequest()
{
// show UI notification...
BackgroundWorkUINotification backgroundWorkUINotification = new BackgroundWorkUINotification();
backgroundWorkUINotification.CancelClicked += HandleBackgroundWorkUINotificationOnCancelClicked;
backgroundWorkUINotification.Show(this);
// start the background worker
this.backgroundWorker.RunWorkerAsync();
}
private void HandleBackgroundWorkUINotificationOnCancelClicked(Object sender, EventArgs e)
{
// UI notification Form, Cancelled
// close the form...
BackgroundWorkUINotification backgroundWorkUINotification = (BackgroundWorkUINotification)sender;
backgroundWorkUINotification.Close();
// stop the background worker thread...
if (backgroundWorker.IsBusy)
backgroundWorker.CancelAsync();
}
private void HandleBackgroundWorkerOnRunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
{
}
private void HandleBackgroundWorkerOnDoWork(Object sender, DoWorkEventArgs e)
{
// do some work here..
// also check for CancellationPending property on BackgroundWorker
}
}
Some days ago I had the same trouble.
This was helped me: "MSDN. How to: Make Thread-Safe Calls to Windows Forms Controls"
I used first aproach (checking InvokeRequired) because it is easiest way.
Hope it is helpful advise!
now program show Messagebox and wait user decision.
How make, that program don't wait?
Show Messagebox, ant keep going.
(I do not need a user action. I just need to show text)
Or maybe a better option than to report the information to a new window?
I hope to understand my problem.
quick and easy way: use a BackgroundWorker to host your long running job and use the worker's events to pop up messages in the UI thread.
edit: might want to display the messages in the form of a message log.
public partial class MainWindow : Form
{
#region Constructor
public MainWindow()
{
InitializeComponent();
}
#endregion
#region Events
private void button_Click(object sender, EventArgs e)
{
listBox.Items.Add("Job started!");
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++)
{
// send data from the background thread
backgroundWorker.ReportProgress(0, i);
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// communicate with UI thread
listBox.Items.Add(string.Format("Received message: {0}", e.UserState));
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
listBox.Items.Add("Job done!");
}
#endregion
}
Create a new Form, put some controls on it and show it to the user:
new PopupForm().Show();
If you just have to show a notification window, then this would be a help that I wrote sometime back; works like Outlook like notification window.