i have a problem with Winforms app with 2 threads: in a second thread I pull messages from WCF service. When there are messages I need to update the GUI : I do this in accordance with patten found here How to update the GUI from another thread in C#? . Here is the code:
private delegate void CWU(int ID);
public void AddNewTab(int id)
{
if (this.tabControl1.InvokeRequired)
{
CWU cb = new CWU(AddNewTab);
this.tabControl1.Invoke(cb,id);
}
else
{
User ToChatWith = ContactsHelper.AllFriends.Find(e => e.ID == id);
tabpage.Text = ToChatWith.ToString();
this.tabControl1.TabPages.Add(tabpage);
this.tabControl1.SelectTab(tabpage);
}
tab is added properly and when we leave this method the app is not responding, no info in debug. When I run my app after adding this tab i get AppHangB1 without any details. Can you help me?
Try this:
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
AddNewTab(id);
});
}
Invoke can hang if the called thread is busy doing something. (You could know this is the case if a BeginInvoke call instead of your Invoke wouldn't hang. Invoke blocks until the call is made successfully, BeginInvoke does not.)
Replace your method with this:
private void dbg(string s)
{
System.Diagnostics.Debug.WriteLine("AddNewTab({0}): {1}",
Thread.CurrentThread.ManagedThreadId, s);
}
public void AddNewTab(int id)
{
try
{
dbg("entered");
if (this.tabControl1.InvokeRequired)
{
new Thread(delegate() { try {
CWU cb = new CWU(AddNewTab);
dbg("calling Invoke");
this.tabControl1.Invoke(cb, id);
dbg("Invoke returned");
} catch (Exception ex) { dbg("" + ex); }
}).Start();
dbg("created sub-thread");
}
else
{
dbg("setting tabpage.Text");
User ToChatWith = ContactsHelper.AllFriends
.Find(e => e.ID == id);
tabpage.Text = ToChatWith.ToString();
dbg("adding tab");
this.tabControl1.TabPages.Add(tabpage);
this.tabControl1.SelectTab(tabpage);
dbg("done adding tab");
}
dbg("leaving");
}
catch (Exception ex)
{
dbg("" + ex);
}
}
Make sure you can find the debugger output in your environment. (Heck, use Console.WriteLine if that helps)
If that doesn't help you diagnose the problem I don't know what will.
Related
I`m using SQLite with multi-threading,my program is working fine but I wish to make it faster. I read that SQLite has 3 threads modes
that can be set compile time(https://www.sqlite.org/threadsafe.html) where the default is "Serialized" but from what I read, the "Multi-thread" would be faster for me.
What I don't understand is how to set SQLite to "Multi-thread" mode in Visual Studio 2013.Anyone know how can I do this? I already found questions talking about this subject but none of them showed clearly how to set this mode.
This is how to make sqlite work in multiple threads.
Use BlockingCollection with ThreadPool.QueueUserWorkItem.
Any database query are queued and executed in FIFO (First In First Out) order.
Now the database is never locked while doing any SQL transaction from any thread.
This is an example in C#.
public class DatabaseQueueBus
{
private BlockingCollection<TransportBean> _dbQueueBus = new BlockingCollection<TransportBean>(new ConcurrentQueue<TransportBean>());
private CancellationTokenSource __dbQueueBusCancelToken;
public CancellationTokenSource _dbQueueBusCancelToken { get => __dbQueueBusCancelToken; set => __dbQueueBusCancelToken = value; }
public DatabaseQueueBus()
{
_dbQueueBusCancelToken = new CancellationTokenSource();
DatabaseQueue();
}
public void AddJob(TransportBean dto)
{
_dbQueueBus.Add(dto);
}
private void DatabaseQueue()
{
ThreadPool.QueueUserWorkItem((param) =>
{
try
{
do
{
string job = "";
TransportBean dto = _dbQueueBus.Take(_dbQueueBusCancelToken.Token);
try
{
job = (string)dto.DictionaryTransBean["job"];
switch (job)
{
case "SaveClasse":
//Save to table here
break;
case "SaveRegistrant":
//Save Registrant here
break;
}
}
catch (Exception ex)
{//TODO: Handle this exception or not
}
} while (_dbQueueBusCancelToken.Token.IsCancellationRequested != true);
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
}
});
}
}
I am facing issue when i got exception in threading. My Code is as follows:
Task.Factory.StartNew(() => ComputeBackgroundAdjudicationTask(taskId, ComputeBackgroundAdjudication));
And ComputeBackgroundAdjudicationTask method is as follows:
private void ComputeBackgroundAdjudicationTask(long taskId, Action<int> completedAdjudicationJobHandler)
{
//My Logic
completedAdjudicationJobHandler(1);
}
Now what iam facing issue is in my logic suppose some exception is coming i want to log into some text file.
After i searched in net i found some answer is as follows.
Task.Factory.StartNew(() =>ComputeBackgroundAdjudicationTask(taskId, ComputeBackgroundAdjudication))
.ContinueWith(
task =>
{
if (task.Exception != null)
task.Exception.Handle(ex =>
{
System.IO.File.AppendAllText(#"C://test.txt", "Error:" + ex.Message + "\r\n");
return true;
});
}, TaskContinuationOptions.OnlyOnFaulted
);
Now its logging into text file. After logging into text file the thread is not starting again. Please help me to fix this.
Thanks in Advance.
In your example the exception terminates the task/thread and after that you log the cause of the thread termination.
It seems what you are searching for is more of this kind:
private void ComputeBackgroundAdjudicationTask(long taskId, Action<int> completedAdjudicationJobHandler)
{
while(true) {
try {
//My Logic
completedAdjudicationJobHandler(1);
}
catch(Exception ex) {
System.IO.File.AppendAllText(#"C://test.txt", "Error:" + ex.ToString() + "\r\n");
}
}
}
But this seems as if whatever completedAdjudicationJobHandler does is not really well designed.
I want to add: If whatever throws the exception will always throw the exception this leads to an infinite loop.
Edit 2016-01-07: Maybe I misunderstood the wanted effect again. As I understand the last comment you want to do things written at the position of // MyLogic and whether they fail or succeed want completedAdjudicationJobHandler(1); executed. In this case the code example would be:
private void ComputeBackgroundAdjudicationTask(long taskId, Action<int> completedAdjudicationJobHandler)
{
try {
//My Logic
}
catch(Exception ex) {
System.IO.File.AppendAllText(#"C://test.txt", "Error:" + ex.ToString() + "\r\n");
}
finally {
completedAdjudicationJobHandler(1);
}
}
The MessageBox.Show call below shows "Inner". Is this a bug?
private void Throw()
{
Invoke(new Action(() =>
{
throw new Exception("Outer", new Exception("Inner"));
}));
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Throw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // Shows "Inner"
}
}
I had a look at the reference source for System.Windows.Forms.Control, and the code that deals with Invoke looks like this:
try {
InvokeMarshaledCallback(current);
}
catch (Exception t) {
current.exception = t.GetBaseException();
}
GetBaseException:
public virtual Exception GetBaseException()
{
Exception inner = InnerException;
Exception back = this;
while (inner != null) {
back = inner;
inner = inner.InnerException;
}
return back;
}
So apparently it's like this by design. The comments in the source offer no explanation as to why they do this.
EDIT: Some site that is now gone claims this comment came from a guy at Microsoft:
Based on the winform comfirmation in the record, our analysis is
correct of the root cause and this behavior is intended. The reason was to
prevent the user from seeing too much of the Windows.Forms internal mechanisms.
This is because the winform's default error dialog also leverages Application.ThreadException to show the exception details. .Net Winform
team trims the other exceptions information so that the default error
dialog will not display all the details to the end user.
Also, some MSFTs have sugguested to change this behavior. However, .Net
Winform team thinks that changing the exception to throw is a breaking
change and for this reason WinForms will keep sending the innermost exception to the Application.ThreadException handler.
The OP doesn't seem to be interested in a work-around. Anyhow, this is mine:
public static object InvokeCorrectly(this Control control, Delegate method, params object[] args) {
Exception failure = null;
var result = control.Invoke(new Func<object>(() => {
try {
return method.DynamicInvoke(args);
} catch (TargetInvocationException ex) {
failure = ex.InnerException;
return default;
}
}));
if (failure != null) {
throw failure;
}
return result;
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
C# cleanest way to write retry logic?
i having a function contains web service call to the server which fails sometime (unable to connect remote server error) due to some disturbance in network. The code is in try catch block. i want to rerun the web service call within try block so that the web call will be done successfully.
const int MaxRetries = 5;
for(int i = 0; i < MaxRetries; i++)
{
try
{
// do stuff
break; // jump out of for loop if everything succeeded
}
catch(Exception)
{
Thread.Sleep(100); // optional delay here
}
}
bool success = false;
int retry = 0;
while (!success && retry<3)
{
try{
// web service calls
success = true;
} catch(Exception) {
retry ++;
}
}
public void Connect()
{
Connect(1);
}
private void Connect(int num)
{
if (num > 3)
throw new Exception("Maximum number of attempts reached");
try
{
// do stuff
}
catch
{
Connect(num++);
}
}
You can put a loop around the try catch block like this:
bool repeat = true
while( repeat){
repeat = false;
try
{
...
}
catch( Exception )
{
repeat = true;
}
}
I think you have your answer here. I just wanted to add a couple of suggestions based on my abundant experience with this problem.
If you add logging to the catch block, you can ascertain how often the web service call fails, and how many attempts were made in all. (Maybe put a toggle in web.config to turn this logging off once the issue subsides.)
That information may prove useful in discussions with system administrators if, for example, the web service provider is within your organization, such as on an intranet.
In addition, if you find that the calls are still failing too often, you could introduce a delay in the catch, so that the retry is not immediate. You might only want to do that on the final attempt. Sometimes it is worth the wait for the user, who doesn't want to lose all the data they have just entered.
And finally, depending on the situation, you could add a Retry button to the UI, so that the user could keep trying. The user could choose to wait five minutes for the network problem to clear itself up, and click Retry.
Wrap the try/catch in a while loop. Set a flag on success to exit the while (or just break out). Make sure you have some sort of retry limit so it won't keep going forever.
while (true)
{
try
{
// call webservice
// handle results
break;
}
catch (TemporaryException e)
{
// do any logging you wish
continue;
}
catch (FatalException e)
{
// do any logging you wish
break;
}
}
If you want to limit the retries, change the termination condition on the while loop.
void Method()
{
do
{
try
{
DoStuff();
return;
}
catch (Exception e)
{
// Do Something about exception.
}
}
while (true);
}
If you find yourself wanting to do this frequently in your code, you might consider implementing a reusable class that encapsulates the "re-try when an error is encountered" logic. This way, you can ensure that the behavior is standardized throughout your code base, instead of repeated each time.
There's an excellent example available on Dan Gartner's blog:
public class Retrier<TResult>
{
public TResult Try(Func<TResult> func, int maxRetries)
{
return TryWithDelay(func, maxRetries, 0);
}
public TResult TryWithDelay(Func<TResult> func, int maxRetries, int delayInMilliseconds)
{
TResult returnValue = default(TResult);
int numTries = 0;
bool succeeded = false;
while (numTries < maxRetries)
{
try
{
returnValue = func();
succeeded = true;
}
catch (Exception)
{
//todo: figure out what to do here
}
finally
{
numTries++;
}
if (succeeded)
return returnValue;
System.Threading.Thread.Sleep(delayInMilliseconds);
}
return default(TResult);
}
}
Well, the easiest would be to copy the code to the catch-block, right?
Another approach could look like:
private void YourMethodThatTriesToCallWebService()
{
//Don't catch errors
}
public void TryToCallWebService(int numTries)
{
bool failed = true;
for(int i = 0; i < numTries && failed; i++)
{
try{
YourMethodThatTriesToCallWebService();
failed = false;
}catch{
//do nothing
}
}
}
You should put the entire catch block into a while statement:
while(retryCount < MAX_RETRY && !success)
{
try
{
//do stuff , calling web service
success = true;
}
catch
{
retryCount++
success = false;
}
}
Some APIs, like the WebClient, use the Event-based Async pattern. While this looks simple, and probably works well in a loosely coupled app (say, BackgroundWorker in a UI), it doesn't chain together very well.
For instance, here's a program that's multithreaded so the async work doesn't block. (Imagine this is going in a server app and called hundreds of times -- you don't want to block your ThreadPool threads.) We get 3 local variables ("state"), then make 2 async calls, with the result of the first feeding into the second request (so they can't go parallel). State could mutate too (easy to add).
Using WebClient, things end up like the following (or you end up creating a bunch of objects to act like closures):
using System;
using System.Net;
class Program
{
static void onEx(Exception ex) {
Console.WriteLine(ex.ToString());
}
static void Main() {
var url1 = new Uri(Console.ReadLine());
var url2 = new Uri(Console.ReadLine());
var someData = Console.ReadLine();
var webThingy = new WebClient();
DownloadDataCompletedEventHandler first = null;
webThingy.DownloadDataCompleted += first = (o, res1) => {
if (res1.Error != null) {
onEx(res1.Error);
return;
}
webThingy.DownloadDataCompleted -= first;
webThingy.DownloadDataCompleted += (o2, res2) => {
if (res2.Error != null) {
onEx(res2.Error);
return;
}
try {
Console.WriteLine(someData + res2.Result);
} catch (Exception ex) { onEx(ex); }
};
try {
webThingy.DownloadDataAsync(new Uri(url2.ToString() + "?data=" + res1.Result));
} catch (Exception ex) { onEx(ex); }
};
try {
webThingy.DownloadDataAsync(url1);
} catch (Exception ex) { onEx(ex); }
Console.WriteLine("Keeping process alive");
Console.ReadLine();
}
}
Is there an generic way to refactor this event-based async pattern? (I.e. not have to write detailed extension methods for each API thats like this?) BeginXXX and EndXXX make it easy, but this event way doesn't seem to offer any way.
In the past I've implemented this using an iterator method: every time you want another URL requested, you use "yield return" to pass control back to the main program. Once the request finishes, the main program calls back into your iterator to execute the next piece of work.
You're effectively using the C# compiler to write a state machine for you. The advantage is that you can write normal-looking C# code in the iterator method to drive the whole thing.
using System;
using System.Collections.Generic;
using System.Net;
class Program
{
static void onEx(Exception ex) {
Console.WriteLine(ex.ToString());
}
static IEnumerable<Uri> Downloader(Func<DownloadDataCompletedEventArgs> getLastResult) {
Uri url1 = new Uri(Console.ReadLine());
Uri url2 = new Uri(Console.ReadLine());
string someData = Console.ReadLine();
yield return url1;
DownloadDataCompletedEventArgs res1 = getLastResult();
yield return new Uri(url2.ToString() + "?data=" + res1.Result);
DownloadDataCompletedEventArgs res2 = getLastResult();
Console.WriteLine(someData + res2.Result);
}
static void StartNextRequest(WebClient webThingy, IEnumerator<Uri> enumerator) {
if (enumerator.MoveNext()) {
Uri uri = enumerator.Current;
try {
Console.WriteLine("Requesting {0}", uri);
webThingy.DownloadDataAsync(uri);
} catch (Exception ex) { onEx(ex); }
}
else
Console.WriteLine("Finished");
}
static void Main() {
DownloadDataCompletedEventArgs lastResult = null;
Func<DownloadDataCompletedEventArgs> getLastResult = delegate { return lastResult; };
IEnumerable<Uri> enumerable = Downloader(getLastResult);
using (IEnumerator<Uri> enumerator = enumerable.GetEnumerator())
{
WebClient webThingy = new WebClient();
webThingy.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e) {
if (e.Error == null) {
lastResult = e;
StartNextRequest(webThingy, enumerator);
}
else
onEx(e.Error);
};
StartNextRequest(webThingy, enumerator);
}
Console.WriteLine("Keeping process alive");
Console.ReadLine();
}
}
You might want to look into F#. F# can automate this coding for you with its «workflow» feature. The '08 PDC presentation of F# dealt with asynchronous web requests using a standard library workflow called async, which handles the BeginXXX/EndXXX pattern, but you can write a workflow for the event pattern without much difficulty, or find a canned one. And F# works well with C#.