The following method is fired when a CD is inserted or ejected.
The problematic code is noted below.
Everything here is based on stepping through the code with breakpoints.
public void CDREventArrived(object sender, EventArrivedEventArgs e)
{
// Get the Event object and display it
PropertyData pd = e.NewEvent.Properties["TargetInstance"];
if (pd != null)
{
ManagementBaseObject mbo = pd.Value as ManagementBaseObject;
if (mbo.Properties["VolumeName"].Value != null)
{
//This line is executed.
textBox1.Text = "test";
//This line is not executed.
//While stepping through the execution,
//I hit F11 on the line above,
//hoping to get to this next line, but it never happens.
//The form pops back up and the step through is complete.
label1.Text = "test";
}
else
{
//Same problem here. Only the first line is hit.
textBox1.Text = "test";
label1.Text = "test";
}
}
}
A related problem is that while it does hit the code to change the text property of textBox1, the text is not actually changed. I can see this on the form and while stepping through breakpoints. So it appears it hits the code, but never actually executes. I'm wondering why it doesn't continue to all the code in the given conditional.
Here is the code which sets up the delegate. This method is called on FormLoad. I stop the listener on form exit.
private void CreateCDRomListener()
{
WqlEventQuery q;
ManagementOperationObserver observer = new
ManagementOperationObserver();
// Bind to local machine
ConnectionOptions opt = new ConnectionOptions();
opt.EnablePrivileges = true; //sets required privilege
ManagementScope scope = new ManagementScope("root\\CIMV2", opt);
try
{
q = new WqlEventQuery();
q.EventClassName = "__InstanceModificationEvent";
q.WithinInterval = new TimeSpan(0, 0, 1);
// DriveType - 5: CDROM
q.Condition = #"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5";
w = new ManagementEventWatcher(scope, q);
// register async. event handler
w.EventArrived += CDREventArrived;
w.Start();
// Do something usefull,block thread for testing
Console.ReadLine();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
}
}
My first guess is this callback occurs on a thread that is not the UI thread. Try this:
if (InvokeRequired)
{
Invoke(() => textBox1.Text = "test");
}
else
{
textBox1.Text = "test";
}
I think an exception is being triggered at some point.
I would probably put a try/catch in that code to see if something is triggering an exception.
Is there some event handler for the textbox that's being fired when you attempt to change its Text property that is dumping out early?
Related
I have written the following code to publish some articles on the Website:
private void btnTransfer_Click(object sender, EventArgs e)
{
//some codes here
counter = 0;
t = new System.Windows.Forms.Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}
int counter;
void t_Tick(object sender, EventArgs e)
{
string cid = cb_destinationSubject.Items[cb_destinationSubject.SelectedIndex].ToString().Split('|')[0];
var wb = new WebClient();
var data = new NameValueCollection();
data["cid"] = cid;
data["title"] =tb_titlePrefix.Text+ postList.ElementAt(counter)[0]+tb_titleSuffix.Text;
data["content"] =tb_textPrefix.Text+ postList.ElementAt(counter)[1]+tb_textSuffix.Text;
if (listBox_images.Items.Count>0)
data["preview"] = listBox_images.Items[new Random().Next(listBox_images.Items.Count)].ToString();
DateTime dt = selector_first_publish.Value.Value;
dt += TimeSpan.FromMinutes((double)(counter * nud_delay.Value));
data["date_time"] = dt.ToString("yyyy-MM-dd HH:mm:ss");
var response = wb.UploadValues(Settings.ApiUrl+"/api/post.php?action=insert","post", data);
var responseString = Encoding.UTF8.GetString(response);
tb_debug.Text += responseString + "\r\n";
if(responseString.Length>5)
lbl_status.Text = responseString;
else
lbl_status.Text =counter.ToString()+" articles has been saved successfully !";
counter++;
if (counter >= postList.Count)
{
counter = 0;
t.Stop();
MessageBox.Show("Done!");
System.Diagnostics.Process.Start(Settings.ApiUrl);
}
}
This Code was working yesterday, but today when I was publishing some new articles (5 articles) I noticed that the first and second article has been published but the third one has been published more than 10 times, then I stopped the program to see what's the problem.
For troubleshooting I created a break line in the following line:
if (counter >= postList.Count)
And realized the third tick never ends, and Visual Studio debug->continue button gets disabled after the pressing it for the second time, and in the break point line visual studio tells me that frmMain.tick is in process.
I figured out that the only difference of the third article is that the string length of that is much more.
But still, I don't get what the problem is, no errors, no exceptions.
******* EDIT *******
I added try catch block like opewix said, but still there is no exceptions,and publishing the third articles goes on until I stop debuging..
void t_Tick(object sender, EventArgs e)
{
try
{
string cid = cb_destinationSubject.Items[cb_destinationSubject.SelectedIndex].ToString().Split('|')[0];
var wb = new WebClient();
var data = new NameValueCollection();
data["cid"] = cid;
data["title"] =tb_titlePrefix.Text+ postList.ElementAt(counter)[0]+tb_titleSuffix.Text;
data["content"] =tb_textPrefix.Text+ postList.ElementAt(counter)[1]+tb_textSuffix.Text;
if (listBox_images.Items.Count>0)
data["preview"] = listBox_images.Items[new Random().Next(listBox_images.Items.Count)].ToString();
DateTime dt = selector_first_publish.Value.Value;
dt += TimeSpan.FromMinutes((double)(counter * nud_delay.Value));
data["date_time"] = dt.ToString("yyyy-MM-dd HH:mm:ss");
//wb.UseDefaultCredentials = true;
//System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
var response = wb.UploadValues(Settings.ApiUrl+"/api/post.php?action=insert","post", data);
var responseString = Encoding.UTF8.GetString(response);
tb_debug.Text += responseString + "\r\n";
if(responseString.Length>5)
lbl_status.Text = responseString;
else
lbl_status.Text =counter.ToString()+" articles has been saved successfully !";
Application.DoEvents();
counter++;
if (counter >= postList.Count)
{
counter = 0;
t.Stop();
MessageBox.Show("انتقال انجام شد");
System.Diagnostics.Process.Start(Settings.ApiUrl);
}
}
catch(Exception ex)
{
throw ex;
}
}
For more information this is the php code I'm using:
/*.. PHP code was unnecessary so is removed ..*/
You have to wrap your Tick handler into try-catch block and then set a breakpoint to catch block, then you'll see an exception. It seems that you're getting exception after submitting request and counter doesn't increment.
Like Enigmativity said, Application.DoEvents(); was the problem !!!
I still don't believe that my program is working, But that's true , Every time I comment the code he said I get the message "Done" and every time I uncomment that code the tick never ends and publishing the third articles goes on...
The reason I used that code was to update the lbl_status Text,Because In some cases in some other programs I've seen Windows Controls doesn't get updated until I use that Application.DoEvents() ..It seems I should study more about this method..Thanks EveryOne,
i am new in C# so please be patient with me .
i want to make progress bar work with any functions i make in my program
i have class to check if INTERNET available and the connection of database status
and i have "progressBar1" , style is "Marquee"
i just want to indicate that there is a process work "Function" in the program and i don't need to have step or timer to increment it
just make the progress work until the function finish its code and the functions will work in button event (when i push button)
this is my code
class checkInternet
{
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);
public bool checkInternetAvailable()
{
int Desc;
bool result = false;
if (InternetGetConnectedState(out Desc, 0) == true)
{
try
{
dbConnection StartConn = new dbConnection();
SqlConnection MyConnetion = StartConn.GetConnection();
MyConnetion.Open();
if (MyConnetion.State == ConnectionState.Open)
{
result = true;
}
MyConnetion.Close();
}
catch (Exception)
{
result = false;
MessageBox.Show("The database connection does not available, May be because of this reasons: \n\n1- there is a new version of the program avalible. \n2- database has some maintenance. \n\n Please check later :)", "Conection status");
}
}
else
{
result = false;
MessageBox.Show("No internet connection avalible , Please check later :) \nThanks.", "Conection status");
}
return result;
}
}
and this is what i have in my button event
private void button1_Click(object sender, EventArgs e)
{
checkInternet check = new checkInternet();
progressBar1.Value = 0;
do
{
progressBar1.PerformStep();
} while (check.checkInternetAvailable());
}
how can i implement that ?
thanks
As I understand you want user to see progressbar while your check connection task executes in background. checkInternetAvailable would be your background operation and I wouldn't suggest showing messages directly form it. Instead return a custom struct :
public struct ConnectionCheckResult
{
public bool Success;
public string Message;
}
And this will be your button click event handler :
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.Visible = true;
//add code here to be executed on UI thread before connection check
Task.Run(new Action(() =>
{
//Task.Run this code on the thread pool instead of your UI thread. So your code is checking connection while progress bar is still rendering
ConnectionCheckResult res = new checkInternet().checkInternetAvailable();
this.Invoke(new Action(() =>
{
//this.Invoke executes following delegate on UI thread. All UI changes - like progressBar1.Visible = false; need to be made in UI thread.
//add code here to be executed on the UI thread after connection check.
progressBar1.Visible = false;
if (!string.IsNullOrEmpty(res.Message))
MessageBox.Show(res.Message);
}));
}));
//add code to be executed on UI thread at the same time as connection check
}
I know multi-threading is difficult to wrap your head around at first, here's good tutorial with code samples.
Also when your progressbar style is Marquee you don't need to call PerformStep. It will just roll by itself.
EDIT: You should also modify checkInternetAvailable() like so :
public ConnectionCheckResult checkInternetAvailable()
{
int Desc;
ConnectionCheckResult result = new ConnectionCheckResult();
if (InternetGetConnectedState(out Desc, 0) == true)
{
try
{
dbConnection StartConn = new dbConnection();
SqlConnection MyConnetion = StartConn.GetConnection();
MyConnetion.Open();
if (MyConnetion.State == ConnectionState.Open)
{
result.Success = true;
}
MyConnetion.Close();
}
catch (Exception)
{
result.Success = false;
result.Message = "The database connection does not available, May be because of this reasons: \n\n1- there is a new version of the program available. \n2- database has some maintenance. \n\n Please check later :)";
}
}
else
{
result.Success = false;
result.Message = "No internet connection available , Please check later :) \nThanks.";
}
return result;
}
I want to process a large ammount of data stored in a text file. Here is the code I use to make it work faster:
var result = File
.ReadLines(textBox1.Text)
.AsParallel()
.WithDegreeOfParallelism(100)
.Select(line => ProcessLine(line));
The method ProcessLine gets the line then processes it and add it to an ArrayList.
After all the processing is done I load the ArrayList into a Datagrid,
but sometimes it completes all the lines and sometimes it hangs, I don't know why.
Any suggestions ?
Update
Here is the Method ProcessLine
private string ProcessLine(string domain)
{
ProcessStartInfo cmdinfo = new ProcessStartInfo();
cmdinfo.FileName = "cmd.exe";
cmdinfo.Arguments = "/c nslookup";
cmdinfo.RedirectStandardInput = true;
cmdinfo.RedirectStandardOutput = true;
cmdinfo.CreateNoWindow = true;
cmdinfo.UseShellExecute = false;
cmdinfo.RedirectStandardError = false;
Process cmdd = new Process();
cmdd = Process.Start(cmdinfo);
string spf = "none";
createproc:
try
{
cmdd.StandardInput.WriteLine("set q=txt");
cmdd.StandardInput.Flush();
cmdd.StandardInput.WriteLine(domain);
cmdd.StandardInput.WriteLine("exit");
cmdd.StandardInput.WriteLine("exit");
StreamReader r = cmdd.StandardOutput;
//cmdd.WaitForExit();
cmdd.Close();
spf = "";
string rdl = string.Empty;
bool spffound = false;
while (rdl != null)
{
try
{
rdl = r.ReadLine();
if (rdl.Contains("v=spf"))
{
spffound = true;
spf = rdl.Trim();
this.Invoke(new MethodInvoker(delegate
{
textBox2.AppendText("domain found : " + domain + Environment.NewLine + "SPF = " + spf + Environment.NewLine);
textBox2.Update();
}));
break;
}
}
catch (Exception)
{
}
}
if (!spffound)
spf = "none";
nbrDoms++;
this.Invoke(new MethodInvoker(delegate
{
DomsElapsed.Text = nbrDoms + " Domains Elapsed";
DomsElapsed.Update();
}));
SPFRecord srx = new SPFRecord((string)spf.Clone(), (string)domain.Clone());
if (srx == null)
{
cmdd.Kill();
cmdinfo = new ProcessStartInfo();
cmdinfo.FileName = "cmd.exe";
cmdinfo.Arguments = "/c nslookup";
cmdinfo.RedirectStandardInput = true;
cmdinfo.RedirectStandardOutput = true;
cmdinfo.CreateNoWindow = true;
cmdinfo.UseShellExecute = false;
cmdinfo.RedirectStandardError = false;
cmdd = new Process();
cmdd.StartInfo = cmdinfo;
cmdd.Start();
goto createproc;
}
lock (pageManager)
{
pageManager.AddRecord(srx);
}
//this.Invoke(new MethodInvoker(delegate
//{
//}));
}
catch(Exception exc)
{
cmd.Kill();
cmdinfo = new ProcessStartInfo();
cmdinfo.FileName = "cmd.exe";
cmdinfo.Arguments = "/c nslookup";
cmdinfo.RedirectStandardInput = true;
cmdinfo.RedirectStandardOutput = true;
cmdinfo.CreateNoWindow = true;
cmdinfo.UseShellExecute = false;
cmdinfo.RedirectStandardError = false;
cmdd = new Process();
cmdd.StartInfo = cmdinfo;
cmdd.Start();
Thread.Sleep(10);
goto createproc;
}
return "";
}
Read the lines of text into a string, with something like file.readalllines(psudo code)
Basically each thread is locking the other, are you trying this for speed or because the file is too large to fit into memory?
Ok, a few things to mention:
Do not use goto statements - it's hard to understand what your method does. Just move the creation of the Process into a separate method and call that method instead of using goto
Processes do take time to load and quite a lot for what you want to do. To avoid this load penalty, instead of creating and calling a process try to replace that with a method which does the same. There's an example of nslookup without calling the process. Try adapting it to your needs
Remove the locks - if your application somehow gets to use 100 threads the lock is a waste of time. You'll have 99 threads waiting for the other single thread to push its data to the pageManager. As #Mrinal Kamboj pointed out, you can use a thread-safe collection. In this case, use a BlockingCollection<T> and add the results there. At the other end of the queue have the pageManager listening and consuming each item as it arrives.
The UI needs its separate cycles to refresh which also takes time. If pageManager.AddRecord() somehow has to refresh the UI then the other threads won't wait just for the add operation.
UI updates must be done in the thread that created the controls and that thread can't update the UI if it's waiting for another thread.
The overall algorithm should look like this:
public class Engine
{
private readonly BlockingCollection<string> _messagePipeline = new BlockingCollection<string>();
public BlockingCollection<string> MessagePipeline
{
get { return _messagePipeline; }
}
public void Process(string file)
{
File.ReadLines(file)
.AsParallel()
.ForAll(line =>
{
var nsLookupResult = NsLookupMethod(line);
if(nsLookupResult.HasInfoYouNeed)
_messagePipeline.Add(nsLookupResult.DisplayInfo);
});
}
}
public class MainForm : Form
{
private readonly Engine _engine; // ...
private void OnStartButtonClick(object sender, EventArgs e)
{
var cts = new CancellationTokenSource();
_engine.Process(textbox1.Text);
Task.Factory.StartNew(()=>
{
foreach(var message in _engine.MessagePipeline.GetConsumingEnumerable())
{
// show the message
Application.DoEvents(); // allow the app to process other events not just pushing messages.
}
}, cts.Token,
TaskCreationOptions.PreferFairness,
// Specify that you want UI updates to be done on the UI thread
// and not on any other thread
TaskScheduler.FromCurrentSynchronizationContext());
}
}
And that should do it. I do have a (more or less academic) example of this kind of logic in action. The UI update logic is in the MainForm of the application and the processing logic is in an Engine class; have a look there.
I Have try this.
https://stackoverflow.com/a/142069/2126472
like toolStripStatusLabel1.InvokeRequired
but toolStripStatusLabel1 has no InvokeRequired
and I has try this too.
https://stackoverflow.com/a/15831292/2126472
and it error like invalid argument on
SetTextCallback d = new SetTextCallback(SetText);
form.Invoke(d, new object[] { form, ctrl, text });
when I use
ThreadHelperClass.SetText(this, toolStripStatusLabel1, "This text was set safely.");
but not error when I use textBox
My code have method that wait for bool from another method that use Thread to run in background.
Thread t = new Thread(TestRemoteDB);
t.Start();
// In TestRemoteDB() will call updateRemoteDBStatus()
like this
private void updateRemoteDBStatus(bool successful)
{
if (successful)
{
toolStripStatusLabel4.Text = "OK!";
toolStripStatusLabel4.ForeColor = Color.Green;
}
else
{
toolStripStatusLabel4.Text = "Error!";
toolStripStatusLabel4.ForeColor = Color.Red;
}
}
Try this:
this.BeginInvoke((Action)(() => toolStripStatusLabel1.Text = "This text was set safely."));
I have the following code from 'Samples for Parallel Programming with the .NET Framework' MSDN when I was trying to cancel the Genetic generations of monkeys in debugging mode I am getting 'OperationCanceledException was unhandled by user code' on line token.ThrowIfCancellationRequested();. I have added last resort of exception handling 'UnobservedTaskException' but the code is never reaching there. Please help me in finding the problem here:
public MainForm()
{
InitializeComponent();
txtTarget.Text = _targetText;
_uiTasks = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
e.SetObserved();
}
private int _currentIteration;
private CancellationTokenSource _cancellation;
private void btnRun_Click(object sender, EventArgs e)
{
if (_cancellation == null)
{
_cancellation = new CancellationTokenSource();
GeneticAlgorithmSettings settings = new GeneticAlgorithmSettings { PopulationSize = Int32.Parse(txtMonkeysPerGeneration.Text) };
txtBestMatch.BackColor = SystemColors.Window;
lblGenerations.BackColor = SystemColors.Control;
lblGenPerSec.Text = lblGenerations.Text = "-";
lblElapsedTime.Text = "0";
btnRun.Text = "Cancel";
chkParallel.Visible = false;
_startTime = _lastTime = DateTimeOffset.Now;
timerElapsedTime.Start();
// Run the work in the background
_cancellation = new CancellationTokenSource();
var token = _cancellation.Token;
bool runParallel = chkParallel.Checked;
Task.Factory.StartNew(() =>
{
// Create the new genetic algorithm
var ga = new TextMatchGeneticAlgorithm(runParallel, _targetText, settings);
TextMatchGenome? bestGenome = null;
// Iterate until a solution is found or until cancellation is requested
for (_currentIteration = 1; ; _currentIteration++)
{
token.ThrowIfCancellationRequested();
// Move to the next generation
ga.MoveNext();
// If we've found the best solution thus far, update the UI
if (bestGenome == null ||
ga.CurrentBest.Fitness < bestGenome.Value.Fitness)
{
bestGenome = ga.CurrentBest;
_uiTasks.StartNew(() => txtBestMatch.Text = bestGenome.Value.Text);
// If we've found the solution, bail.
if (bestGenome.Value.Text == _targetText) break;
}
}
// When the task completes, update the UI
}, token).ContinueWith(t =>
{
timerElapsedTime.Stop();
chkParallel.Visible = true;
btnRun.Text = "Start";
_cancellation = null;
switch (t.Status)
{
case TaskStatus.Faulted:
MessageBox.Show(this, t.Exception.ToString(), "Error");
break;
case TaskStatus.RanToCompletion:
txtBestMatch.BackColor = Color.LightGreen;
lblGenerations.BackColor = Color.LemonChiffon;
break;
}
}, _uiTasks.Scheduler);
}
else _cancellation.Cancel();
}
You've probably setup Visual Studio to stop on all thrown exceptions. You can either ignore this (hit continue) or disable this option: Debug menu > Exceptions. Clear the checkbox of "Common Language Runtime Exceptions" Thrown column. Alternatively you can uncheck the specific exception (click the Find button and search for OperationCanceledException).
Playing with Tasks on 4.5 and got the same error but for a different reason.
Posting here as this was the top search result and it took me a while to find the cause.
try
{
await Task.Run(() => DoWork());
label1.Text = "Finished.";
}
catch (OperationCanceledException)
{
label1.Text = "Cancelled.";
}
Which ran:
private async void DoWork()
{
// WORK STUFF
{
workerCancel.Token.ThrowIfCancellationRequested();
}
}
Cancelling would cause the unhandled error because I put void instead of Task:
private async Task DoWork()
The exception was actually handled... To ensure just press F5 to see that is's been caught. To set your debugger not to catch user unhandled exceptions press Ctrl + Alt + E and unselect User-unhandled