I am working on signalR. I have a server (ASP .NET) and a client (C# WinForms).
In my client app I have a async method:
public async void conAsync()
{
HubConn = new HubConnection(serverURL);
HubPrx = HubConn.CreateHubProxy("myHUB");
try
{
await HubConn.Start();
richTextBox1.AppendText("connected");
button1.BackColor = Color.Green;
groupBox1.Enabled = true;
groupBox2.Enabled = true;
}
catch(Exception err)
{
// deactive comps
groupBox1.Enabled = false;
groupBox2.Enabled = false;
richTextBox1.AppendText(err.toString());
}
}
The Start Button executes the above method.
I want provide a Stop Button which stops the connection to the server. I read about CancellationToken but I got confused about how to use it in my case.
Actually my button is a CheckBox which acts like a ToggleButton.
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
checkBox1.ForeColor = Color.Green;
conAsync();
}
else
{
//stop conAsync() here
}
}
HubConn.close() solved the problem and it stops the conAsync() ..... i think the cancellation token is not the solution here (i was wrong) but it may be alternative one for another case.
Related
I have this Code to Get a table Data From SQL Server:
public static System.Data.Linq.Table<Equipment> GetEquipmentTable()
{
DataClassesDataContext dc = new DataClassesDataContext();
return dc.GetTable<Equipment>();
}
I Have a Button to call this Function :
private void button_Click(object sender, RoutedEventArgs e)
{
MyListView.DataContext = GetEquipmentTable();
}
My Problem is :When I Disable Communication Between my App and SQL Server Machine and then click this button, It takes a while to throw an Exception that Connect to Database is impossible!!!! My major problem is that my app freezed till this Exception accrued.
Did I missed something ?
Update 1 :
I used async and wait base on Rahul solution
public static async Task<System.Data.Linq.Table<Equipment>> GetEquipmentTable()
{
DataClassesDataContext dc = new DataClassesDataContext();
return dc.GetTable<Equipment>();
}
private async void button_Click(object sender, RoutedEventArgs e)
{
MyListView.DataContext = await GetEquipmentTable();
}
but it still wait for this line of code :
return dc.GetTable<Equipment>();
and UI freezes as well.
I think dc.gettable<> is not waitable or somthing else !!??
When I Disable Communication Between my App and SQL Server Machine and
then click this button
That's obvious right since it tries to connect to the machine (within the Timeout mentioned in connection string) and then throws the exception back once it finds that the server isn't reachable.
major problem is that my app freezed till this Exception accrued
Probably in that case make the method as async method like
public static async Task<System.Data.Linq.Table<Equipment>> GetEquipmentTable()
{
DataClassesDataContext dc = new DataClassesDataContext();
return dc.GetTable<Equipment>();
}
Your event handler
private async void button_Click(object sender, RoutedEventArgs e)
{
MyListView.DataContext = await GetEquipmentTable();
}
You have two problems, the app freezing is because you are not using asynchronous programming.
The delay before the connection exception is because the client side app waits until the connection timeout timer finishes (30 seconds default).
Try using async await on your database calls to free up the UI.
Try changing the connection timeout to 5 seconds in the connection string.
Change in connection string:
"Data Source=...;Connect Timeout=5"
Use await as in the answer from Rahul. +1
You could also test a simple SqlConnection.Open
private static bool OpenSqlConnection(string connectionString)
{
bool return = false;
try
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
return = true;
}
catch (Exception ex)
{
return = false;
}
finally
{
connection.Close();
}
return return;
}
Could use SqlConnection.OpenAsync.
SqlConnection con = new SqlConnection("connection string");
bool resp = false;
try
{
con.OpenAsync();
resp = true;
}
catch (SqlException ex)
{
//use the ex message
resp = false;
}
catch (Exception ex)
{
resp = false;
}
finally
{
con.Close();
}
I have buttons that give the ability to start or stop the app's background service, but for some reason my 'else' call in the button's click event isnt being activated if the service is already running.
Heres the whole button code, hope someone knows why it doesnt call:
private void StartServiceButton_Click(object sender, EventArgs e)
{
if (Application.Context.GetSystemService("com.prg.NotificationService") == null)
{
Application.Context.StartService(intent);
}
else
{
Toast.MakeText(this, "Service already running", ToastLength.Long).Show();
}
}
im caching intent in OnCreate, here is the setup:
intent = new Intent(Application.Context, typeof(NotificationService));
Here is about the GetSystemService method, this method is to get system service not to get your custom service. You need use ActivityManager to get all service which is running on your device and find which one is what you want to start or stop.
Please use the under code to achieve your goal:
private void StartServiceButton_Click(object sender, System.EventArgs e)
{
MyService myService = new MyService();
if (!isServiceRun("MyService"))
{
Toast.MakeText(this, "Service not running", ToastLength.Long).Show();
Application.Context.StartService(intent);
}
else
{
Toast.MakeText(this, "Service already running", ToastLength.Long).Show();
StopService(new Intent(this,typeof(MyService)));
}
}
public bool isServiceRun( string className)
{
bool isRun = false;
ActivityManager activityManager = (ActivityManager)this.GetSystemService(Context.ActivityService);
IList<ActivityManager.RunningServiceInfo> serviceList = activityManager.GetRunningServices(40);
int size = serviceList.Count;
for (int i = 0; i < size; i++)
{
Android.Util.Log.Error("Service Name=====", serviceList[i].Service.ClassName);
if (serviceList[i].Service.ClassName.Contains(className) == true)
{
isRun = true;
break;
}
}
return isRun;
}
Note:
Here is the usage about Service in Xamarin.Android, please don't forget add [Service] attribute.
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;
}
To get used to and get trained using Backgroundworker for my Project, i used a sample code which runs smoothly except when it comes to handling error condition it doesn't allow me to use (e.Error!=null) facility of RunWorkerCompletedEventArgs e.I want to handle error like the way cancel and successful completion works for me.
Suggestions please!
Following is the code:
private void DoWork(object sender, DoWorkEventArgs e)
{
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
if (this.backgroundWorker.CancellationPending)
{
e.Cancel = true;
break;
}
// report progress
this.backgroundWorker.ReportProgress(-1, string.Format("Performing step {0}...", i + 1));
// simulate operation step
System.Threading.Thread.Sleep(rand.Next(1000, 10000));
//setting simulateError to true after inducing error(a button)
if (this.simulateError)
{
this.simulateError = false;
//needs a code to use (e.Error!=null) in
RunWorkerCompleted().
//A jump to RunWorkerCompleted is required here.
}
}
}
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// hide animation
this.pictureBox.Image = null;
// show result indication
if (e.Cancelled)
{
////works nice
this.labelProgress.Text = "Operation cancelled by the user!";
this.pictureBox.Image = Properties.Resources.WarningImage;
}
else
{
//doesn't execute at all....why?
if (e.Error != null)
{
this.labelProgress.Text = "Operation failed: " + e.Error.Message;
this.pictureBox.Image = Properties.Resources.ErrorImage;
}
else
{
//works nice
this.labelProgress.Text = "Operation finished successfuly!";
this.pictureBox.Image = Properties.Resources.InformationImage;
}
}
// restore button states
this.buttonStart.Enabled = true;
this.buttonCancel.Enabled = false;
this.buttonError.Enabled = false;
}
I induce error using simulateError ,for the purpose to show peculiar error message how should i use
if (e.Error != null)
{
this.labelProgress.Text = "Operation failed: " + e.Error.Message;
My Program isn't coming to private void RunWorkerCompleted(object sender, ,RunWorkerCompletedEventArgs e) in case of error. In other cases(cancellation,succesful completion) it executes right.
To get used to and get trained using Backgroundworker for my Project
Why would you do that? Task.Run() is better than BackgroundWorker in every way.
Now to your actual question: to cause an error in a BackgroundWorker, use the standard mechanism for that in .Net: exceptions:
if (this.simulateError)
{
this.simulateError = false;
throw new Exception("Simulating error.");
}
I have a TCP client written in C#, and I use backgroundWorker to connect the server, something like this:
void ConnectToServer() {
try {
bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(bwConnector_DoWork);
bwConnector.RunWorkerCompleted = new RunWorkerCompletedEventHandler(bwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
e.Result = true;
} catch {
e.Result = false;
}
}
void bwConnector_DoWork(object sender, DoWorkEventArgs e) {
clientSocket = new Socket(xxxxxx);
clientSocket.Connect(xxxx);
this.networkStream = new NetworkStream(this.clientSocket);
this.bwReceiver = new BackgroundWorker();
this.bwReceiver.DoWork += new DoWorkEventHandler(StartReceive);
........
}
And I have a timer to check clientSocket.Connected is true or false, if false, I will call ConnectToServer() again for another connection attempt.
The problem is everytime I closed the application and reopen it, it seems that the last socket still remain there and have 2 sockets with the same IP but different ports connecting to the server.
Even I have something like this:
void bwConnector_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
((BackgroundWorker)sender).Dipose();
if (!((bool)e.Result)) {
Debug.Log("failed");
} else {
Debug.Log("success");
}
}
For disconnection, I have such codes:
System.Net.NetworkInformation.NetworkChange.NetworkAvailablilityChanged += new System.Net.NetworkInformation.NetworkAvailabilityChangedEventHandler(NetworkAvailabilityChanged);
private void NetworkChange_NetworkAvailabilityChanged(object sender , System.Net.NetworkInformation.NetworkAvailabilityEventArgs e)
{
if ( !e.IsAvailable )
{
this.OnNetworkDead(new EventArgs());
this.OnDisconnectedFromServer(new EventArgs());
}
else
this.OnNetworkAlived(new EventArgs());
}
...............
public event DisconnectedEventHandler DisconnectedFromServer;
protected virtual void OnDisconnectedFromServer(EventArgs e)
{
if ( DisconnectedFromServer != null )
{
DisconnectedFromServer(this , e);
}
}
...........
void StartReceive(xxxxxxxxx) {
while (this.clientSocket.Connected) {
.........
}
this.Disconnect();
}
bool Disconnect() {
if (this.clientSocket != null && this.clientSocket.Connected) {
try {
this.clientSocket.Shutdown(SocketShutdown.Both);
this.clientSocket.Close();
return true;
} catch {
return false;
}
}
}
Thanks for help.
Responding here as suggested by SO.
Sadly, real world applications tend to fail and often time unexpected things happen. Being accidently closed by a user might be the most obvious "unexpected thing". I would have made sure that, if nothing else, at least everything is cleaned up on exit.
In the end, its all upto you.