I'm working on a project to display the information received from the API in a DataGridView. I have created a Thread to update the DataGridView that runs the DataGridView refresh method every 5 seconds in a parallel process. But when the program runs, after one step of the Thread, the information is placed in the DataGridView, I get this error in the second step of calling the "RefreshGridData" function by Thread:
exception {"Object reference not set to an instance of an object."} System.NullReferenceException
Here are the codes of the Thread and the DataGridView refresh function called by that:
Data Refreshing Thread
{
trdRefresh = new Thread(() =>
{
while (true)
{
try
{
RefreshGridData();
Thread.Sleep(1000 * 5);
}
catch (Exception ex)
{
Thread.Sleep(1000 * 5);
}
}
});
trdRefresh.Start();
}
RefreshGridData:
var response = DataReceiver();
var data = JsonConvert.DeserializeObject<List<ClientPulsLog>>(response);
var source = new BindingSource
{
DataSource = Data
};
DataGridView1.DataSource = source; //The error occurs here
DataGridView1.Refresh();
Data Receiver:
public static string DataReceiver()
{
try
{
using (var client = new HttpClient())
{
var url = $"http://{"127.0.0.1:9094"}/DataProvider/TotalData/";
var request = "{\"MessageType\":"+ typeId + "}";
var content = client.GetAsync(url).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
return content;
}
}
catch
{
}
return string.Empty;
}
Important note
The interesting thing is that when I put a Watch Point at the beginning of the error line, whenever it arrives and pauses while debugging, if I wait a second and then click on the Continue button, the program will continue without any problems.
How can I solve this problem?
Thanks.
Related
I recently solved an issue where my program was crashing while using a BackgroundWorker.
I do not fully understand why there was a problem in the first place. When the thread has it's apartment state set to STA the Process memory increases until the program throws the exception "Unable to allocate environment handle", at first I thought it was an issue with the Database not being able to process the queries quickly enough. The bottom chart on the picture below shows the program running with the thread set to STA. You can see a steady increase in usage until it drops off almost completely. That is when the exception is thrown.
When the thread is running with the ApartmentState set to MTA, the top chart shows it behaving as expected, there is a increase in usage, then it starts a pattern of using and free the memory.
TLDR:
Why does a thread using the Apartment state STA have an issue.
Below I have included some relevant code.
BackgroundWorker myWorkerBee;
List<Customers> AllCustomers
private void btnStartConversion_Click(object sender, RoutedEventArgs e)
{
myWorkerBee = new Thread(myWorkerBee_DoWork);
myWorkerBee.SetApartmentState(ApartmentState.STA);
myWorkerBee.Start();
{
private void myWorkerBee_DoWork()
{
GetOldData(); //Creates Customer object and fills AllCustomers list
AddCustomers();
}
There is no issue with the program if it doesn't use the AddNewCustomerConvert(); Method.
private void AddCustomers()
{
for (int i = 0; i < AllCustomers.Count; i++)
{
AllCustomers[i].AddNewCustomerConvert();
}
}
This method exclusively calls the RawQuery(); Method, or methods that only call the RawQuery(); method
//REFERENCED PROGRAM
AddNewCustomerConvert()
{
//40 or so insert statements.
databaseConnection.RawQuery("//INSERT STATEMENT");
}
Sends Queries to the database
//REFERENCE DLL
public OdbcDataReader RawQuery(string query_to_perform)
{
// This method executes a query in the specific database that you
// are connected to.
System.Data.Odbc.OdbcCommand command = null;
// holds the query sent to the database
System.Data.Odbc.OdbcDataReader result_reader = null;
// The query is put into an OdbcCommand object and sent to the database. The
// return result will then be given back to the caller.
try
{
if (loggingEnabled)
{
myLog = File.AppendText(loggingFileName);
myLog.WriteLine(query_to_perform);
myLog.Close();
myLog.Dispose();
}
command = new System.Data.Odbc.OdbcCommand(query_to_perform, this.database_connection);
result_reader = command.ExecuteReader();
this.successful_query = true;
this.error_message = "";
}
catch (System.Data.Odbc.OdbcException ex)
{
this.successful_query = false;
this.error_message = ex.Message;
//destroy the connection on a failure
database_connection = new OdbcConnection();
throw;
}
return result_reader;
}
I have a few functions in a Solidworks Addin which call on a VBA macro (Via the runMacro2 method) a co-worker has been working on for the last few weeks. In his code he calls a Solidworks function which, under certain, unknown conditions, hangs for a long period of time. How long seems to depend upon the size and quantity of bodies in the part. Considering at least one of the functions we want to run this from i automatic, this just wont do.
I have tried using the Thread.Join(int) method (shown below) but it doesnt work. I also tried modifying the code from this answer Close a MessageBox after several seconds with the same results. Is there anything I can do either in C# or VBA to handle a timeout for this without re-writing his entire macro?
public void runBB()
{
Stopwatch testStop = new Stopwatch();
Thread workerThread = new Thread(bbRun);
testStop.Start();
workerThread.Start();
if (!workerThread.Join(50))
{
workerThread.Abort();
testStop.Stop();
MessageBox.Show("Unable to generate Bounding Box after " + testStop.ElapsedMilliseconds/1000 + " seconds. Please enter data manually.", "Solidworks Derped Error.");
}
return;
}//Still uses Macro (2-5-16)
public static void bbRun()
{
iSwApp.RunMacro2(macroPath + "BOUNDING_BOX.swp", "test11", "main", 0, out runMacroError);
return;
}
I was getting this same exact issue with SOLIDWORKS hanging on an open of a file. Almost all reference on SO was that you should never do this, but in this scenario, you either have to close it or wait forever. In C# I created a callWithTimeout method:
private void callWithTimeout(Action action, int timeoutMilliseconds, String errorText) {
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action();
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds)) {
wrappedAction.EndInvoke(result);
} else {
threadToKill.Abort();
throw new TimeoutException(errorText);
}
}
Then the code that was hanging put in a block as such:
bool timedOut = false;
try {
callWithTimeout(delegate() {
// code that hangs here
}, 60000, "Operation timed out. SOLIDWORKS could not open the file. This file will be processed later.");
} catch (TimeoutException){
timedOut = true;
} finally {
if(timedOut) {
Process[] prs = Process.GetProcesses();
foreach (Process p in prs) {
if (p?.ProcessName.Equals("SLDWORKS") ?? false)
p?.Kill();
}
}
}
Im working on an EConnect integration Windows form app in C#. Im having a lot of trouble testing my connection string. Basically I give the user the option to change the connection string so I want to be able to test it. As far as I know EConnect doesnt have any built in functions that test the connection so I'm writing a pretty crude function to do it myself. Just for everyones information the connection string consists of a server name that the GP databases are located on and a database name.
The particulars of the actual test function I dont think are that important but the main issue is within that function I call an eConnect method called getEntity, this method uses the connection string and if the connection string is right it will pull information. If the database name is wrong the getEntity method will return an eConnect exception which is easy enough to catch, however if the server name is wrong the getEntity method will just spin and my app gets stuck.
Im trying to write something where I can possibly run my test function asynchronously and simultaneously check for a timeout or the econnect exception. This is where I get stuck, I cant for the life of me get it to work. Here is the first thing I tried (this is in my TestConnection method):
task = Task.Factory.StartNew(() => requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml), token);
try
{
if (!task.Wait(timeOut, token))
{
Console.WriteLine("The server name is incorrect - task timed out");
return false;
}
}
catch (ThreadInterruptedException)
{
return false;
}
catch (AggregateException ae)
{
ae.Handle((x) =>
{
if (x is eConnectException) // This we know how to handle.
{
Console.WriteLine("Incorrect Database Name! -- " + x.Message);
return false;
}
return false; // Let anything else stop the application.
});
}
This would catch the cases where the server was wrong and if my econnect method would just time out. But it never caught the eConnect exception, Visual Studio would break the app and tell me I had an unhandled exception.
Here is what Im trying now, this is the full class I have for my form. Here I'm trying to use IAsyncResult and using a WaitHandle to check to see if the function completes or times out. This seems to work sometimes, it works for a correct string and for when the database is wrong, and sometimes it works for when the server is wrong, but once I test for a wrong server name it doesnt work correctly for anything else anymore. Is there something I'm missing or is there a better way to run the getentity method in TestGPConnection and check to see if it hasnt completed after a certain time period and if it hasnt kill that method and have the user reenter a server name?
public partial class UpdateGPConnection : Form
{
Task task;
AsyncCallback cb;
public delegate string startProcessToCall();
startProcessToCall sp2c;
public UpdateGPConnection()
{
InitializeComponent();
this.txtDatasourceName.Text = ConfigurationManager.AppSettings.Get("GPDataServer");
this.txtDatabaseName.Text = ConfigurationManager.AppSettings.Get("GPDatabase");
cb = new AsyncCallback(startProcessCallback);
sp2c = new startProcessToCall(TestGPConnection);
}
public void startProcessCallback(IAsyncResult iar)
{
startProcessToCall mc = (startProcessToCall)iar.AsyncState;
bool result = mc.EndInvoke(iar);
Console.WriteLine("Function value = {0}", result);
}
private void btnUpdate_Click(object sender, EventArgs e)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["GPDataServer"].Value = txtDatasourceName.Text.ToUpper();
config.AppSettings.Settings["GPDatabase"].Value = txtDatabaseName.Text.ToUpper();
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
GPCongfigSettings.GPConnectionString = #"data source=" + txtDatasourceName.Text.ToUpper() + ";initial catalog=" + txtDatabaseName.Text.ToUpper() + ";integrated security=SSPI;persist security info=False;packet size=4096";
IAsyncResult asyncResult = null;
asyncResult = sp2c.BeginInvoke(cb, null);
timer1.Enabled = true;
Thread.Sleep(0);
bool test = asyncResult.AsyncWaitHandle.WaitOne(15000);
if (test)
{
try
{
string testResult = sp2c.EndInvoke(asyncResult);
}
catch (Exception exc)
{
Console.WriteLine(exc.Message);
}
}
bool result = asyncResult.IsCompleted;
asyncResult.AsyncWaitHandle.Close();
this.Close();
}
public string TestGPConnection()
{
eConnectMethods requester = new eConnectMethods();
try
{
// Create an eConnect document type object
eConnectType myEConnectType = new eConnectType();
// Create a RQeConnectOutType schema object
RQeConnectOutType myReqType = new RQeConnectOutType();
// Create an eConnectOut XML node object
eConnectOut myeConnectOut = new eConnectOut();
// Populate the eConnectOut XML node elements
myeConnectOut.ACTION = 1;
myeConnectOut.DOCTYPE = "GL_Accounts";
myeConnectOut.OUTPUTTYPE = 2;
myeConnectOut.FORLIST = 1;
myeConnectOut.WhereClause = "(ACTNUMST = '99-9999-99-999')";
// Add the eConnectOut XML node object to the RQeConnectOutType schema object
myReqType.eConnectOut = myeConnectOut;
// Add the RQeConnectOutType schema object to the eConnect document object
RQeConnectOutType[] myReqOutType = { myReqType };
myEConnectType.RQeConnectOutType = myReqOutType;
// Serialize the eConnect document object to a memory stream
MemoryStream myMemStream = new MemoryStream();
XmlSerializer mySerializer = new XmlSerializer(myEConnectType.GetType());
mySerializer.Serialize(myMemStream, myEConnectType);
myMemStream.Position = 0;
// Load the serialized eConnect document object into an XML document object
XmlTextReader xmlreader = new XmlTextReader(myMemStream);
XmlDocument myXmlDocument = new XmlDocument();
myXmlDocument.Load(xmlreader);
string reqDoc = requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml);
return "Correct Connection";
}
catch (eConnectException exc)
{
Console.WriteLine(exc.Message);
return "eConnect Excpetion";
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return "Excpetion";
}
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
}
You are not handling the eConnectException. You are showing a message in the Console and then essentially rethrowing the exception by returning false.
If you do handle an exception then you should return true to avoid rethrowing it:
catch (AggregateException ae)
{
ae.Handle((x) =>
{
if (x is eConnectException) // This we know how to handle.
{
Console.WriteLine("Incorrect Database Name! -- " + x.Message);
}
return x is eConnectException; //rethrow anything that is not an eConnectException
});
}
Here is my problem:
I have a Wcf service on a server that has two methods:
Synchronize() and GetExecutionState().
I also have a client that is to call those operations.
The Synchronize() executes lots of things and in several steps so at each step i update a local (inside the wcf) variable and i publish this variable via the GetExecutionState() operation The operation can fail, can take eons to execute and so on.
So, when i consume this service on the client, say on somebutton_click() event,
what i want to happen is this:
show infinite progressbar (main thread, UI);
start a thread to run Synchronize();
start another thread to keep reading GetExecutionState() every x minutes and in the event of a connection failure (which is the main reason i need this last thread) cancel the whole thing.
I dont know lot about threading, but so far i have implemented 1 and 2. Can someone help me with 3?
I am using devExpress and here is my relevant code.
SERVER PART:
public class SyncServerService :ISyncServer {
protected CsNo Node;
protected SyncState State;
public SyncServerService() {
State = SyncState.None;
Node = null;
}
public SyncState OperationState() {
return State;
}
public void PutComputerName(string value) {
var man = new CsNoManager();
Node = man.GetByMachineName(value);
}
public bool CanSync() {
var man = new ViewSyncLogManager();
var log = man.GetByMachineName(Node.MachineName);
return !log[0].IsInSync;
}
public CommandExecutionResponse Synchronize() {
CommandExecutionResponse res = null;
var logManager = new CsLogSyncManager();
var log = logManager.GetByNode(Node.IDNo);
State=SyncState.Syncing;
//step 1
State = SyncState.State2;
//...step n
State = SyncState.SomeOtherState;
//somewhere along the path create the res object
return res;
}
}
I read somewhere that with WCF, i can call operations both sync and async, so i dont think i have to mess with the server part regarding my requirements.
Client part:
On the button click that starts the process:
private void cmdSync_Click(object sender, EventArgs e) {
pgbSync.Properties.Stopped = false;
backgroundWorker1.RunWorkerAsync();
}
pgbSync is of type MarqueeProgressBar, a DevExpress progressbar that has infinite loop
backgroundWorker1 is of type System.ComponentModel.BackgroundWorker...supposedly runs tasks on the background.
It's start and finish methods are:
START:
private void StartSync(object sender, DoWorkEventArgs e) {
try {
//setting up wcf link properties
var manager = new CsConfiguracaoManager();
var address = manager.SyncAppServiceAddress();
var binding = new NetTcpBinding {
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
CloseTimeout = new TimeSpan(0, 0, 30, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 30, 0, 0),
ReceiveTimeout = new TimeSpan(0, 0, 30, 0, 0),
SendTimeout = new TimeSpan(0, 0, 30, 0, 0)
};
var factory = new ChannelFactory<ISyncServer>(binding, new EndpointAddress(address));
var proxy = factory.CreateChannel();
proxy.PutComputerName(PcName);
//checking if i can sync first
if (proxy.CanSync() == true) {
ExecutionResponse = proxy.Sync();
}
else {
//set up messages to show errors
}
}
catch (DataException dataErr) {
//set up appropriate messages
}
catch (EndpointNotFoundException err) {
//set up appropriate messages
}
catch (Exception masterErr) {
//set up appropriate messages
}
}
FINISH:
private void FinishSync(object sender, RunWorkerCompletedEventArgs e) {
pgbSync.Properties.Stopped = true;
//process ExecutionResponse object from FinishSync
}
This all runs, but if i disconnect the network after the process has started (we are anticipating lots of communication issues) the process will only throw an exception after the 30 minutes set in the service have passed.
Thats why i want to introduce a 3rd step where i check every x minutes for the output of OperationState.
If i cannot read it, i abort the operation, if it has a null or err state i also stop.
Any ideas?
I am note sure if you need a 3rd thread for this.
Have you tried System.Timers.Timer to have an event generated every x seconds and doing your checks?
If that event does not occur you can go with a BackgroundWorker which will have a loop with Thread.Sleep(250) and cancelation checks.
I have a page which is fetching data from a webservice using async call.
If i get the response from webservice control goes to catch where a message box is pooped.
The code is given below:
string uri = "http://free.worldweatheronline.com/feed/weather.ashx?key=b7d3b5ed25080109113008&q=Mumbai&num_of_days=5";
UriBuilder fullUri = new UriBuilder("http://free.worldweatheronline.com/feed/weather.ashx");
fullUri.Query = "key=b7d3b5ed25080109113008&q=Mumbai&num_of_days=5";
HttpWebRequest forecastRequest = (HttpWebRequest)WebRequest.Create(fullUri.Uri);
// set up the state object for the async request
ForecastUpdateState forecastState = new ForecastUpdateState();
forecastState.AsyncRequest = forecastRequest;
// start the asynchronous request
forecastRequest.BeginGetResponse(new AsyncCallback(HandleForecastResponse), forecastState);
This part is response
private void HandleForecastResponse(IAsyncResult asyncResult)
{
try
{
// get the state information
ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState;
HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest;
// end the async request
forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult);
Stream streamResult;
string newCityName = "";
//int newHeight = 0;
// get the stream containing the response from the async call
streamResult = forecastState.AsyncResponse.GetResponseStream();
// load the XML
XElement xmlWeather = XElement.Load(streamResult);
}
catch (Exception ex)
{
MessageBox.Show("Connection Error");
}
}
Problem :
when the page is loaded it starts fetching data from webservice(consider the case when the web service is not responding and control goes to catch part).
In the mean time if we press the back button or navigate the page the message box popps on the new page.
How could i stop that.
Thanks and Regards
Haven't tested it, but it may work:
1/ Store the value of the NavigationService.CurrentSource property somewhere it can be retrieved (the best would be in the asyncState parameter, but a property may work as well
2/ In the HandleForecastResponse, compare the old and new value of the NavigationService.CurrentSource. This way, you should be able to deduce if the active page has changed or not.
ifixed that problem by add
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
});
try this
private void HandleForecastResponse(IAsyncResult asyncResult)
{
try
{
// get the state information
ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState;
HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest;
// end the async request
forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult);
Stream streamResult;
string newCityName = "";
//int newHeight = 0;
// get the stream containing the response from the async call
streamResult = forecastState.AsyncResponse.GetResponseStream();
// load the XML
XElement xmlWeather = XElement.Load(streamResult);
}
catch (Exception ex)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Connection Error");
});
}
}
Finally solved it.
catch (Exception x)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var currentPage = ((App)Application.Current).RootFrame.Content as PhoneApplicationPage;
if ((currentPage.ToString()).Equals("MumbaiMarathon.Info.News"))
{
MessageBox.Show("Connection Error");
}
});
}
I just checked at the time of popping the message box the name of the Current UI application page. If its same as the page from which message box is initiated than it pops otherwise not.