First of all, I apologize for my English.
I have a method to verify my connection to SQL (TestConneccion), and I use a timer to verify it every second.
The problem is when I lose the connection, my application hangs while it tries to connect. I'm using task to avoid this, but I am new to C#.
I would really appreciate the help
public string testConeccion()
{
var archivo = "";
try
{
odb = DatabaseFactory.CreateDatabase("TESTCONECTION");
ocn = odb.CreateConnection();
if (ocn.State == ConnectionState.Closed)
{
ocn.Open();
}
ocn.Close();
archivo = "true";
}
catch (InvalidOperationException ex)
{
archivo = ex.Message;
}
catch (Exception ex)
{
archivo = ex.Message;
}
finally
{
ocn.Close();
}
return archivo;
}
private void timerMesas_Tick(object sender, EventArgs e)
{
Task<string> T1 = Task.Run<string>(() => oClasePublica.testConeccion());
if (T1.Result == "true")
{
btnEstado.Image = new System.Drawing.Bitmap(TOUCHREST.Properties.Resources.Status_32x32);
}
else
{
btnEstado.Image = new System.Drawing.Bitmap(TOUCHREST.Properties.Resources.Warning_32x32);
}
}
Make your timer tick handler async and await your task. This will run the method asynchronously and prevent the rest of your application from hanging while it runs.
private async void timerMesas_Tick(object sender, EventArgs e)
{
string T1 = await Task.Run<string>(() => oClasePublica.testConeccion());
if (T1 == "true")
{
btnEstado.Image = new System.Drawing.Bitmap(TOUCHREST.Properties.Resources.Status_32x32);
}
else
{
btnEstado.Image = new System.Drawing.Bitmap(TOUCHREST.Properties.Resources.Warning_32x32);
}
}
The ocn.Close() in the try code is not needed because the finally will do it. Also catch (InvalidOperationException ex) is not needed because catch (Exception) covers it.
You cannot do Task.Run and then immediately test the Result because the task has not yet finished! Normally you use Task.Wait(); however this will then block your main thread.
I suggest using a BackgroundWorker that continuously checks the connection and then reports it progress. This avoids the issue of changing the image on a non-UI thread.
Related
I have an async function which still freezes / lags the UI thread for me when I execute it. This is my function calling it.
private void TcpListenerLogic(object sender, string e)
{
Application.Current.Dispatcher.BeginInvoke((Action)async delegate {
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
// Get properties for new anchor
string testInformation = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + results.test_id);
}
}
catch (Exception exception)
{
// Writing some Trace.WriteLine()'s
}
});
}
And this is the async function that freezes my UI Thread
public static async Task<string> getJsonFromURL(string url)
{
try
{
string returnString = null;
using (System.Net.WebClient client = new System.Net.WebClient())
{
returnString = await client.DownloadStringTaskAsync(url);
}
return returnString;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return null;
}
}
I already tried to make everything in TcpListenerLogic run in a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
}).Start();
Which resulted in the whole UI completely freezing. And I tried to make TcpListenerLogic async and await the dispatcher, which also made everything freeze permanently. I also tried to make TcpListenerLogic async and leave the dispatcher. The dispatcher is only there because I normally have some UI code in there, which I left out for my tests.
I have ventured far through the internet, but no BackgroundWorker, ThreadPool or other methods helped me in my endeavour.
If anyone has help for this particular problem, or a resource that would improve my understanding of async functions in C#, I would much appreciate it.
Edit
As requested a deeper insight in how this event handler is called.
I have System.Net.Websocket, which is connected to the Backend API I am working with and triggers an event, everytime he receives new Data. To guarantee the socket listens as longs as it is open, there is a while loop which checks for the client state:
public event EventHandler<string> TcpReceived;
public async void StartListener(string ip, int port, string path)
{
try
{
using (client = new ClientWebSocket())
{
try
{ // Connect to backend
Uri serverUri = new Uri("ws://" + ip + ":" + port.ToString() + path );
await client.ConnectAsync(serverUri, CancellationToken.None);
}
catch (Exception ex)
{
BackendSettings.IsConnected = false;
Debug.WriteLine("Error connecting TCP Socket: " + ex.ToString());
}
state = client.State;
// Grab packages send in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
try
{
// **Just formatting the received data until here and writing it into the "message" variable**//
TcpReceived(this, message);
// Close connection on command
if (result.MessageType == WebSocketMessageType.Close)
{
Debug.WriteLine("Closing TCP Socket.");
shouldstayclosed = true;
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
break;
}
state = client.State;
}
catch
{
BackendSettings.IsConnected = false;
state = client.State;
}
}
state = client.State;
}
}
catch (Exception ex)
{
// Some error messages and settings handling
}
}
The Event has a handler attached:
TcpReceived += TcpListener_TcpReceived;
And this is the Handler, which calls the previously seen "TcpListenereLogic".
private void TcpListener_TcpReceived(object sender, string e)
{
TcpListenerLogic(sender, e);
//App.Current.Dispatcher.BeginInvoke(new Action(() => {
// TcpListenerLogic(sender, e);
//}));
//new Thread(() =>
//{
// Thread.CurrentThread.IsBackground = true;
// TcpListenerLogic(sender, e);
//}).Start();
}
I previously had the "TcpListenereLogic" as the handler, but I wanted to try different methods to call it. I also left in the commented out part, to show how the call of "TcpListenereLogic" looked already. All my attempts were with all mentioned setups and sadly lead to nothing.
Thank you very much #TheodorZoulias for helping me to find the solution to my problem.
It turns out it wasn't the async function itself, but rather how often it gets called. It got called roughly ~120 times every second.
My solution starts by calling the Listener method over a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
MainWindow.tcpListener.StartListener(ip, portNumber, "/api/");
}).Start();
To limit the amount of calls that happen every second I added a dispatcher timer, that resets a bool after it has been used for a call, by my Event.
readonly System.Windows.Threading.DispatcherTimer packageIntervallTimer =
new System.Windows.Threading.DispatcherTimer();
bool readyForNewPackage = true;
private void ReadyForPackage(object sender, EventArgs e)
{
readyForNewPackage = true;
}
public async void StartListener(string ip, int port, string path)
{
packageIntervallTimer.Interval = TimeSpan.FromMilliseconds(50);
packageIntervallTimer.Tick += (s, e) => { Task.Run(() => ReadyForPackage(s, e)); };
packageIntervallTimer.Start();
Then I wrapped everything inside the while loop into an if condition based on the bool, the most important part was to have my "event EventHandler TcpReceived" in there:
// Grab packages sent in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
if (readyForNewPackage == true)
{
readyForNewPackage = false;
try
{
....
TcpReceived(this, message);
....
}
catch
{
...
}
}
}
I added my TcpListenerLogic to the Eventhandler:
TcpReceived += TcpListenerLogic;
And my TcpListenerLogic now looked like this (names have been changed):
private async void TcpListenerLogic(object sender, string e)
{
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
string testID = "";
if (results.test_id is JValue jValueTestId)
{
testID = jValueTestId.Value.ToString();
}
else if (results.test_id is string)
{
testID = results.test_id;
}
// Get properties for new object
string information = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + testID );
if (information != null)
{
await App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// Create object out of the json string
TestStatus testStatus = new TestStatus();
testStatus.Deserialize(information);
if (CommunicationCommands.isNameAlreadyInCollection(testStatus.name) == false)
{
// Add new object to the list
CommunicationCommands.allFoundTests.Add(testStatus);
}
}));
{
}
catch (Exception exception)
{
....
}
}
Adding a new Thread to execute any step results in problems, so keep in mind that all this uses the thread created at the beginning for "StartListener"
Here are the two alternatives i tried for catching errors, they both seem to do the same thing.. but is one preferable over the other and why ?
Alt 1:
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
try
{
Task t = Task.Run(() =>
{
_someObj.SomeMethod();
});
await t; //wait here, without blocking...
}
catch (Exception ex)
{
string errMsg = ex.Message + Environment.NewLine;
errMsg += "some unhandled error occurred in SomeMethod";
Log(errMsg);
return; //<-- bypass below code on error...
}
//other code below... does not execute...
DoSomethingElse();
}
Alt 2:
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
bool errOccurred = false;
Task t = Task.Run(() =>
{
try
{
_someObj.SomeMethod();
}
catch (Exception ex)
{
string errMsg = ex.Message + Environment.NewLine;
errMsg += "some unhandled error occurred in SomeMethod";
Log(errMsg);
errOccurred = true;
}//end-Catch
});
await t; //wait here, without blocking...
if (errOccurred) return; //<-- bypass below code on error...
//other code below... does not execute...
DoSomethingElse();
}
Better option is to refactor part of the code into a separate method returning a bool indicating that whether to proceed or not.
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
bool success = await SomeMethodAsync();
if (!success)
{
return;
}
//other code below... does not execute...
DoSomethingElse();
}
private async Task<bool> SomeMethodAsync()
{
try
{
await Task.Run(() => _someObj.SomeMethod());
return true;
}
catch (Exception ex)
{
string errMsg = string.Format("{0} {1}some unhandled error occurred in SomeMethod",
ex.Message, Environment.NewLine);
Log(errMsg);
return false;
}
}
It's better to refactor the code than putting it all at the same place.It's better to catch the exception within your delegate if all you need to do is log it.
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
await Task.Run(() =>
{
try
{
DoSomeWork();
}
catch (Exception ex)
{
log.Error(ex.Message);
}
});
}
However If you have another method DoSomethingElse() which might be affected by the outcome of the Task.It's better to wrap try catch around await
private async void BtnClickEvent(object sender, RoutedEventArgs e)
{
try
{
await Task.Run(() =>
{
try
{
DoSomeWork();
}
catch (Exception ex)
{
log.Error(ex.Message);
}
});
DoSomethingElse();
}
catch(Exception ex)
{
}
}
As with anything it depends.
I'd say refactor the Task.Run() section into a separate async Task method, much like Sriram Sakthivel's answer, is in general a good thing. It avoids the use of a captured bool in the lambda as in version 2, and it lets you write code that expresses intent more concisely.
That said, I would carefully consider if the "catch all -> log -> ignore" pattern is what you want. In general: catch specific exceptions and handle them specifically. For all other exceptions, you might log them, but still rethrow them with "throw;" or "throw new MoreSpecificException(originalException);".
With that in mind I would suggest that if you do the catch all approach you should do the catch all as in version 1.
To keep readability high, make the code concise with clear intent, and be explicit about handling exceptions, I would write it something like this:
private async void BtnClick(object sender, RoutedEventArgs e)
{
try
{
if (await TryDoSomethingAsync())
{
DoSomeMoreStuff();
}
}
catch (Exception ex)
{
// I am sure it is fine that any and all exceptions can be logged and ignored.
Log(ex);
// And maybe even notify the user, since I mean, who monitors log files anyway?
// If something that shouldn't go wrong goes wrong, it's nice to know about it.
BlowUpInYourFace(ex);
}
}
private async Task<bool> TryDoSomethingAsync()
{
return await Task.Run<bool>(() =>
{
try
{
_myService.DoSomething();
}
catch (SomeKnownException ske)
{
// An expected exception which is fine to ignore and return unsuccessful.
Log(ske);
return false;
}
catch (SomeOtherKnownException soke)
{
// Expected exception that indicates something less trivial, but could be more precise.
throw new MyMorePreciseException(soke);
}
// Nothing went wrong, so ok.
return true;
});
}
For now I was using Parallel methods to check urls for 200 status code, but this was slow method. Now I'm trying to move my code to await/async methods but it doesn't working
private async void button1_Click(object sender, EventArgs e)
{
DateTime start = DateTime.Now;
var timerPostingSpeed = new Timer(state =>
{
TimeSpan elapsed = DateTime.Now - start;
string postingSpeed = string.Format("{0:0}",
finishedUrls * 60 / (int)elapsed.TotalSeconds);
UpdatingLabel(label1, postingSpeed);
}, null, 5000, 10000);
IEnumerable<string> urls = File.ReadLines("urls.txt");
var engine = Python.CreateEngine();
var scriptSource =
engine.CreateScriptSourceFromString(#"
if Open(__URL).Result:
print 1
");
await urls.ForEachAsync(20, async line =>
{
try
{
var adderEngine = new SpeedEngine();
// int zz = await adderEngine.Open(line);
// return;
ScriptScope scope = engine.CreateScope();
scope.SetVariable("__URL", line);
scope.SetVariable("Open",
new Func<string, Task<int>>(adderEngine.Open));
try
{
await scriptSource.Execute(scope);
}
catch (UnboundNameException une)
{
MessageBox.Show(une.Message,
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Unbound_Name_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (SyntaxErrorException see)
{
MessageBox.Show(
string.Format("{0}\nLine: {1}\nCode: {2}",
see.Message,
see.Line, see.GetCodeLine()),
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (MissingMemberException mme)
{
MessageBox.Show(mme.Message, "Missing Member",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (ArgumentTypeException ate)
{
MessageBox.Show(string.Format("{0}", ate.Message),
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (SystemExitException)
{
}
catch (Exception exc)
{
MessageBox.Show(string.Format("{0}", exc.Message),
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
MessageBox.Show(string.Format("{0}","OK"),
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception exc)
{
MessageBox.Show(string.Format("{0}", exc.Message),
msg.
MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
Interlocked.Increment(ref finishedUrls);
numericUpDown1.Invoke(new MethodInvoker(delegate
{
numericUpDown1.Value++;
}));
}
});
timerPostingSpeed.Dispose();
}
}
public async Task<int> Open(string siteUrl)
{
Uri newUri;
if (!Uri.TryCreate(siteUrl, UriKind.Absolute, out newUri)) return 0;
_uri = _openUri = newUri;
_req = new HttpRequestMessage(HttpMethod.Get, _uri);
_response = await _httpClient.SendAsync(_req);
if (_response == null || !_response.IsSuccessStatusCode)
{
return 0;
}
return 1;
}
I need to use Iron Python - without it (when I uncomment await adderEngine.Open(line); return;) everything works ok. But with Iron Python my app stopped at *_response = await _httpClient.SendAsync(_req);* without errors. Also I noticed when I replace
await urls.ForEachAsync(20, async line =>
with:
await urls.ForEachAsync(1, async line =>
it's working
ForEachAsync: http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx
Any help?
If your Python code is calling Task.Result, and you're on a UI thread (as appears to be the case), you can cause a deadlock (I explain this fully on my blog). In short, the async method (Open) is trying to resume execution on the UI thread, but the UI thread is blocked by calling Result.
AFAIK, Python does not have async/await support, but you should be able to use ContinueWith (meh) or write some kind of bridge between Task and Twisted's Deferred (much cooler).
This is really short question. I don't understand try-catch mechanism completely.
This is my current code:
public static void WriteText(string filename, string text)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
}
}
Background:
Im writing application that shares configuration files with another application.
I need some dialog messagebox with "retry" and "abort" buttons, when that file is used by other application. When that message will appear - I will close that other application and I will try to rewrite that file again by pressing "Retry" button.
Whatr we have is using a counter for re-tries and possibly a thread sleep.
So something like
int tries = 0;
bool completed = false;
while (!completed)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
completed = true;
}
catch(Exception exc)
{
tries++;
//You could possibly put a thread sleep here
if (tries == 5)
throw;
}
}
Even though there's a good answer already I'll submit one that's more tuned towards the OP's question (let the user decide instead of using a counter).
public static void WriteText(string filename, string text)
{
bool retry = true;
while (retry)
{
try
{
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
retry=false;
}
catch(Exception exc)
{
MessageBox.Show("File is probably locked by another process.");
// change your message box to have a yes or no choice
// yes doesn't nothing, no sets retry to false
}
}
}
If you need more info on how to implement the messagebox check out the following links;
http://msdn.microsoft.com/en-us/library/0x49kd7z.aspx
MessageBox Buttons?
I would do it like that:
public static void WriteText(string filename, string text, int numberOfTry = 3, Exception ex = null)
{
if (numberOfTry <= 0)
throw new Exception("File Canot be copied", ex);
try
{
var file = new System.IO.StreamWriter(filename);
file.Write(text);
file.Close();
}
catch (Exception exc)
{
WriteText(filename,text,--numberOfTry,ex);
}
}
I like it more like this (example tries to save a RichTextBox on close and allows retrying save or aborting close):
protected override void OnClosing(CancelEventArgs e)
{
if (richTextBox_Query.Modified)
{
DialogResult result;
do
try
{
richTextBox_Query.SaveFile(
Path.ChangeExtension(Application.ExecutablePath, "sql"),
RichTextBoxStreamType.UnicodePlainText);
result = DialogResult.OK;
richTextBox_Query.Modified = false;
}
catch (Exception ex)
{
result = MessageBox.Show(ex.ToString(), "Exception while saving sql query",
MessageBoxButtons.AbortRetryIgnore);
e.Cancel = result == DialogResult.Abort;
}
while (result == DialogResult.Retry);
}
base.OnClosing(e);
}
I saw several posts with similar problem but no solution works :/
I debug a windows service by using a console application. It executes tasks on website and must be able to collect http code status for create logs. As you can see, sensitive code is in try/catch.
When I debug (F5), I have a WebException that is not caught. When I run (CTRL + F5), the exception's message is write in my console and stops my program.
This is my code :
public partial class Schedulor : ServiceBase
{
void RunTasks()
{
schedulor.Start();
List<Task> task = new List<Task>();
foreach (TaskPlanner tp in listTp)
{
if (tp.CountDown == 0 && tp.IsRunning == false)
{
// Initialisation lors de GetTasks()
tp.IsRunning = true;
try
{
task.Add(Task.Factory.StartNew(() => tr = tp.ExecuteBot.Execute())); // WEBEXECPTION HERE (cannot find 404)
}
catch (Exception e)
{
if (e is WebException)
{
// treatment
}
}
}
}
Task.WaitAll(task.ToArray());
CreateLogs();
}
}
public class Bot : IBot
{
public TaskResult Execute()
{
TaskResult tr = new TaskResult();
int codeResponse, timeout;
string credentials;
try
{
WebRequest wrSettings = WebRequest.Create(settings.Url);
// treatment
}
catch (Exception e)
{
//Console.WriteLine(e.Message);
if (e is WebException)
{
var code = ((HttpWebResponse)((WebException)e).Response).StatusCode;
if ((int)code != settings.HttpResponse)
{
tr.MyResult = TaskResult.Result.nok;
goto next;
}
else tr.MyResult = TaskResult.Result.ok;
}
}
next:
return tr;
}
}
I do not understand why my catch does not work. I need to treat this information because the task can test if a website return 404 or anything else.
Thanks in advance
EDIT : -----------
I reduce code as it requests because deleted code does not the real problem
You should catch that exception in task. Add another method, and create your tasks similar to:
task.Add(Task.Factory.StartNew(() => Process(tp)));
void Process(TaskPlanner tp)
{
try
{
tp.ExecuteBot.Execute();
}
catch (WebException wex)
{
}
}