We are trying to develop a WCF service for executing a long running task. The method implementing the long running task spawns a new task and immediately returns to the client(which in our case is an .aspx page) if the task has been successfully queued. The service is running on its own application pool with no recycling and single InstanceContextMode.
WCF Service
[OperationContract]
public bool testThreadAbortException()
{
Task.Factory.StartNew
(
() =>
{
try
{
//long operation
int i = 0;
while (i < 250)
{
int j = 0;
while (j < 2000000) j++;
i++;
}
ThreadState state = Thread.CurrentThread.ThreadState;
string dummy = "finished ";
}
catch(Exception exception)
{
ThreadState state = Thread.CurrentThread.ThreadState;
string msg = exception.Message;
Exception inner = exception.InnerException;
}
}
);
return true;
}
Client
protected void btnRun_Click(object sender, EventArgs e)
{
_default.IISHOST_ETLSchedulerServiceReference.ETLSchedulerServiceClient client = new _default.IISHOST_ETLSchedulerServiceReference.ETLSchedulerServiceClient();
bool ret = client.testThreadAbortException();
}
Now the problem is that while the testThreadAbortException method is being executed i catch the Thread was being aborted exception ( this always happends after the client has exited the event handler method ). The weird thing is that this exception is only thrown the first time (ie if i press the run button again the code executes fine). I have to restart my local IIS to replicate the error again.
Does anyone have a clue know why this happens??
Is there a better way to implement what i am trying to archive besides switching to a windows service??
As it seems its Mcafee antivirus after all that is accessing the hash.web file. Confirmed with process monitor. Go figure.....
For more info check this post. Issue similar to mine.
Related
So my issue here is simple. I've designed a WinForms application and it works well on my machine (Win7), and in fact other machines, yet when I run the application on a Windows 10 2016 LTSB machine, my background threads do not work as expected - yet some do perform as expected.
Application flow:
Wait 1 minute (obj1 with Threading.Timer)
Post event (a string message from obj1 when MainWindow calls obj1)
Update form text (with info from event message)
Perform operation (background thread)
Post event message (from background thread to MainWindow)
Wait random period (obj1 with Threading.Timer)
Post event (a string message from obj1)
Update form
Wait 1 minute
Now for some privacy policies/reasons I cannot share the exact things that operate here and how the classes are structured, but here is a rudimentary class structure:
class MainWindow
{
List<Controller> controllers = new List<Controller>();
List<ControllerDisplay> controllerDisplays = new List<ControllerDisplay>();
Queue<string> requests = new Queue<string>();
private void AppLifetimeLoopCallback(object state)
{
while (requests.Count > 0)
{
string request = requests.Dequeue();
string response = controllers[i].ProcessRequest(request);
string anotherResponse = controllerDisplays[i].ProcessResponse(response);
if (!string.NullOrWhiteSpace(anotherResponse))
{
requests.Enqueue(anotherResponse);
}
}
for (int i = 0; i < controllers.Count; i++)
{
requests.Enqueue("STATE?");
}
timer.Change(300, Threading.Timeout.Infinite);
}
}
class Controller
{
public string ProcessRequest(string request)
{
switch (request)
{
case "STATE?":
if (shouldRequest)
{
return "REQ:1234";
}
else if (isProcessing)
{
return "PRQ:1234";
}
else
{
return "IDLE";
}
break;
case "APPROVE":
shouldRequest = false;
isProcessing = true;
thread = new Threading.Thread(new ThreadStart(() =>
{
Threading.Thread.Sleep(300);
isProcessing = false;
return "RQF:1234";
})
{
IsBackground = true,
};
thread.Start();
break;
case "DENY:
shouldRequest = false;
break;
}
}
}
class ControllerDisplay
{
public string ProcessResponse(string response)
{
switch (request.Substring(0, 4))
{
case "REQ:":
thread = new Threading.Thread(new ThreadStart(() =>
{
// perform some checks
if (isValid)
{
return "APPROVE";
}
else
{
return "DENY";
}
})
{
IsBackground = true,
};
thread.Start();
break;
case "RQF:":
thread = new Threading.Thread(new ThreadStart(() =>
{
// finalize and cleanup request bits
return "APPROVE";
})
{
IsBackground = true,
};
thread.Start();
break;
case "PRQ:":
// update UI
break;
}
}
}
Now firstly, I know there seems to be some discrepancy between the millisecond delay in the code and the description of the flow - however note that there is another Thread in the Controller which toggles the shouldRequest value at this minute interval which switches up the response messages to perform the "request" when the device's state is requested.
Secondly I also have registered to the UnhandledException as well as the ThreadException events of the application which should log any undesired behaviour that occurred.
Third, note that in MainWindow there is a Threading.Timer (not in code - I know) that is updating the UI with the current date and time every second.
Now the issue here that I've noticed is that on the Win10LTSB2016 machine, the application stops performing the background operations. Some of the threads must have just died off or something as i.e. the date and time keeps updating as expected, but one controller will be stuck in request state and another in a request complete state - and no error messages logged / MessageBox. Note that the machine does not go into any sleep or hibernate state in this period that the threads just stop, and another note is that the memory sockets is 1, not 2 (as I read that this could affect the threads losing communication with each other if they are compartmentalized to different processor groups and your application is not written to handle this).
Closing off:
Note that when I perform checks to see if I should i.e. start the request process thread in the Controller class so as to not do the same request over and over until state change is detected, I do the following:
lock (checkLock)
{
if (isProcessingRequest)
{
break;
}
else
{
lock (resourceLock)
{
isProcessingRequest = true;
}
}
}
thread = new Threading.Thread(new ThreadStart(() =>
{
lock (resourceLock)
{
// finalize and cleanup request bits
isProcessingRequest = false;
}
return "APPROVE";
})
{
IsBackground = true,
};
thread.Start();
I'm closing this question as it is complete hogwash and I apologize to those for the time they spent reading this.
So the manual locks on the Queue<T> kept causing a deadlock before, thus they were removed. Now it seemed to resolve the issue at first, but long running tests proved every now and again (what I thought was a Windows issue) a deadlock occurred.
The reason I had thought this was a Windows issue is because someone telling me that this is what they experienced on Windows and it is definitely a Windows issue. Not looking down on anyone, but he does not do threading as he does not know how and the mentioned result was from his attempt to do threading. Lesson learned here.
Thanks guys and/or gals.
EDIT:
The issue was resolved and long running tests are looking very promising thus far. To achieve this, I simply changed Queue<T> to ConcurrentQueue<T> and a few modifications to code where needed (i.e. ConcurrentQueue<T>.Clear() does not exist where Queue<T>.Clear() does).
Setup:
C#, .Net 4.5.2. Windows service; fires up 30 background workers that will dequeue items from an external queue and connect to DB to run some logic. Service is 32-bit running on a 64-bit Win 2012 server.
Problem:
For some reason, if there is a SQL Exception, all threads stop responding one by one, but the service shows that its still running under the services.msc.
Details:
The DB is known to go offline every once in a while, and anytime it happens, our service stops working. In most cases, we don't have a choice but to restart it manually.
Current code base is not using the OnCompleted events to catch an exception and there is no additional logic to reset the threads or something similar along these lines.
What I can't understand:
I can't wrap my head around that when an exception takes place, does the background worker continues to run, so in this case, SQL exception, it waits for the default connection timeout, 15 or 30 seconds, and then it forgets about the exception that just happened, and moves on to the next item?
For some reason, it seems to me that when an exception happens, that thread is pretty much useless, and once all the threads deal with this exception, they don't really do anything behind the scenes, but for some reason, the service itself shows that its still running, and doesn't exit out.
Debugging on local:
When I'm debugging on local (VS), after a few minutes, all threads do seem to exist with code 0 and the service exists out as well, but I'm unable to see this behaviour on the server.
Question:
Is it possible that all foreground threads die/aren't doing anything but the service itself stays alive? Can you guys recommend a good way to reset all the threads if a known but unhandled exception occurs?
Code:
Service.cs
protected override void OnStart(string[] args)
{
try
{
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
for (int i = 0; i < 30; i++)
{
stt = new STF.STT();
stt.STP(check, i);
alBots.Add(stt);
count++;
check = false;
System.Threading.Thread.Sleep(3000);
}
}
catch (Exception err)
{
throw;
}
}
Start Thread
public Boolean STP(bool check, int ctr)
{
threadCheck = check;
try
{
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
bwAppprocessor = new BackgroundWorker();
bwAppprocessor.WorkerReportsProgress = true;
bwAppprocessor.RunWorkerCompleted += BwAppprocessor_RunWorkerCompleted;
bwAppprocessor.DoWork += BwAppprocessor_DoWork;
tmrPollChk = new System.Timers.Timer();
tmrPollChk.Elapsed += TmrPollChk_Elapsed;
tmrPollChk.Interval = Properties.Settings.Default.ThreadPollTimer;
tmrPollChk.Start();
bwAppprocessor.RunWorkerAsync();
return true;
}
catch (Exception err)
{
return false;
}
DoWork
private void BwAppprocessor_DoWork(object sender, DoWorkEventArgs e)
{
DoWorkProcesses();
}
Actual work
void DoWorkProcesses()
{
try
{
//Business logic-connect to DB
return;
}
catch (Exception err)
{
//It logs error here
}
}
ONComplete
private void BwAppprocessor_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
//Not much going on here; no error handling :(
//or checking for e.Error :(
}
catch (Exception err)
{
//Useless
}
}
In your case SCM started your service, and it will remain in "running" state after OnStart method exit. You have to sign to SCM somewhere that your job finished. Therefore call Stop after your last BackgroundWorker completed.
I'm looking for a way to invoke a function on a different thread.
We are working with a server(gRPC) which sends out data when it receives it, a task is running at the client and will proceed the loop once it receives new data(stream.MoveNext()).
Once it receives new data it will invoke a function, although this is done within a different thread
NOTE: I'm not getting the Cross-Thread Exception, this is because its disabled during build and testing on developer machine is impossible.
public static async Task ButtonStream()
{
var rpc = buttonClient.buttonPressed(new ButtonsSubscription());
try
{
using (rpc)
{
var stream = rpc.ResponseStream;
while (await stream.MoveNext())
{
if (stream.Current.Id >= persistantDic.Count)
{
int a = stream.Current.Id;
int b = persistantDic.Count;
//Console.WriteLine("{0} >= {1}", a,b);
throw new Exception("Something went wrong");
}
else
{
buttonPressed = stream.Current.Id;
gRPCEvents.ButtonUpdates?.Invoke ();
Console.WriteLine("Invoked from thread: "+Thread.CurrentThread.ManagedThreadId);
}
}
}
}
catch (RpcException e)
{
throw;
}
}
ButtonUpdates?.Invoke runs a function within main(threadID 1), When i press F1(Testing purpose only) i see that its running the function on Thread 1, but when it gets invoked its running function on Thread 4 (or 9, changes sometimes).
EDIT
The function on main thread is subscribed to the delegate invoked, which will be invoked by a task on thread 4
Resolved,
WaveEngine was so kind to provide me with an easy solution to hook in to their main thread
WaveServices.Dispatcher.RunOnWaveThread(() =>
{
//Any code here for execution
});
To clarify on my question I've been developing an app that does a lot of database updates / web service calls based on the input from a user (using an excel spreadsheet). If there are a lot of updates to make the process can take in excess of 20 minutes to run.
To stop my UI from freezing / timing out I've been looking into multithreading so I can run my long running process in an asynchronous manner and in the mean time simply displaying an animated gif whilst the process runs.
This all seems to run nicely at the moment with my test data, but when I substitute in the actual long running process I get an error regarding HttpContext.Current.User.Identity.Name. I've read up on this and from this article1 I took it to mean that if you set the 'Async' property to 'true' in the page directive and used the RegisterAsyncTask method you could then access HttpContext.Current. However, for me this doesn't seem to be true. I'm sure it's something I'm doing, so here is my code (I've mainly been using the following articles to write this article2 and article3):
ASP.NET page
<%# Page Title="Home Page" Async="true" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.cs" Inherits="MyApp.Index" %>
C# - RegisterAsyncTask is done on a button click, which starts the long running process:
protected void ProcessUpdates()
{
//Register async task to allow the processing of valid updates to occurr in the background
PageAsyncTask task = new PageAsyncTask(OnBegin, OnEnd, OnTimeOut, null);
RegisterAsyncTask(task);
}
IAsyncResult OnBegin(Object sender, EventArgs e, AsyncCallback cb, object state)
{
return Worker.BeginWork(cb, state);
}
private void OnEnd(IAsyncResult asyncResult)
{
//UpdateResults list should now have been filled and can be used to fill the datagrid
dgProcessedUpdates.DataSource = Worker.UpdateResults;
dgProcessedUpdates.CurrentPageIndex = 0;
dgProcessedUpdates.DataBind();
lblProgress.Text = "Update Results: update success / failure is shown below";
}
private void OnTimeOut(IAsyncResult asyncResult)
{
lblProgress.Text = "The process has timed out. Please check if any of the updates have been processed.";
}
C# - Worker class
public class Worker
{
public static List<AuditResult> UpdateResults = new List<AuditResult>();
private delegate void del();
//This method is called when the thread is started
public static IAsyncResult BeginWork(AsyncCallback cb, object state)
{
del processing = DoUpdateProcessing;
return processing.BeginInvoke(cb, state);
}
private static void DoUpdateProcessing()
{
//UpdateResults = ExcelFileProcessing.PassValidUpdates();
//Testing
Thread.Sleep(5000);
int i = 0;
while(i < 10)
{
AuditResult ar = new AuditResult();
ar.Result = "Successful";
ar.JobNumber = (1000 + i).ToString();
ar.NewValue = "Test New Value " + i.ToString();
ar.ResultDate = DateTime.Now.ToString();
ar.UserName = HttpContext.Current.User.Identity.Name;
UpdateResults.Add(ar);
i++;
}
}
}
Initially my test code didn't include a call to HttpContext.Current.User.Name for ar.UserName but after my issues with putting back in the call to ExcelFileProcessing.PassValidUpdates() with this I decided to do it. When I reach that part (ar.UserName = HttpContext.Current.User.Identity.Name) it says 'Object reference not set to an instance of an object', which suggests the HttpContext isn't carried across to the second thread. How can I do this?
UPDATE
I've currently reverted back to my previous code (that wasn't initially working) and simply passed the HttpContext.Current as a variable to my DoWork method as per this SO question like this:
Create 2nd thread
protected void ProcessValidUpdates()
{
Worker workerObject = new Worker();
HttpContext ctx = HttpContext.Current;
Thread workerThread = new Thread(new ThreadStart(() =>
{
HttpContext.Current = ctx;
workerObject.DoWork();
}));
workerThread.Start();
//Loop until worker thread activates
while (!workerThread.IsAlive) ;
//Put main thread to sleep to allow the worker thread to do some work
Thread.Sleep(1000);
//Request the worker thread stop itself
workerObject.RequestStop();
//Use the Join method to block the current thread until the object's thread terminates
workerThread.Join();
//UpdateResults list should now have been filled and can be used to fill the datagrid
dgProcessedUpdates.DataSource = Worker.UpdateResults;
dgProcessedUpdates.CurrentPageIndex = 0;
dgProcessedUpdates.DataBind();
lblProgress.Text = "Update Results: update success / failure is shown below";
}
Worker Class
public class Worker
{
//volatile hints to the compiler that this data member will be accessed by multiple threads.
private volatile bool _shouldStop;
public static List<AuditResult> UpdateResults = new List<AuditResult>();
//This method is called when the thread is started
public void DoWork()
{
while (!_shouldStop)
{
//Testing
Thread.Sleep(5000);
int i = 0;
while (i < 10)
{
AuditResult ar = new AuditResult();
ar.Result = "Successful";
ar.JobNumber = (1000 + i).ToString();
ar.NewValue = "Test New Value " + i.ToString();
ar.ResultDate = DateTime.Now.ToString();
ar.UserName = HttpContext.Current.User.Identity.Name;
UpdateResults.Add(ar);
i++;
}
}
}
public void RequestStop()
{
_shouldStop = true;
}
}
This seems to work in that I can now access HttpContext.Current and the username I expect. I think this is probably to some degree what some of you were proposing anyway. I appreciate the solution suggested by Andrew Morton but at the moment that would require a significant rewrite. At the moment my process already calls a web service to do the database stuff and returns a success or failure result. It also has to call another BPEL service directly. As such I suspect there may be further performance hits if I had to wrap all this into another web service. In addition, most calls to the process won't be that long running (probably less than 10 mins), so this is really only to address the few requests that exceed 20 mins. Finally, this is only likely to be used by 1 or 2 people, so it's unlikely to have a huge number of requests at 1 time.
However, bearing in mind my current solution, is there anything I should be aware of that might trip me up? IIS causing issues? Any additional help would be very much appreciated.
I have a site on a shared server. I need to have a BATCH job and I do that in another thread. It can run up to 1 hour (I ping the site so the worker process does not stop).
I went down the road of tying to get the current context. After many hours of research and searching it cannot be done. In a new thread the httpcontent.current is not there, it is not the same thread as the user was accessing, so the context did not carry over, and you cannot access the logged in user, since they are not logged into that thread.
I have a web application that does the following:
You click a button to instantiate a singleton, which creates a Thread. That Thread runs continuously doing some HTTP requests to gather some data. You can click a stop button that calls the Abort() method on the thread and the application stops making HTTP requests. When I start/stop it manually, everything works fine.
My problem occurs when ever I "touch" web.config. The CPU (w3wp.exe process) spikes and the website stops responding. Does anybody know why this is happening? Shouldn't an update to web.config reset everything?
Sample code is below:
private static MyProcessor mp = null;
private Thread theThread = null;
private string status = STOP;
public static string STOP = "Stopped";
public static string START = "Started";
private MyProcessor()
{}
public static MyProcessor getInstance()
{
if (mp == null)
{
mp = new MyProcessor();
}
return mp;
}
public void Start()
{
if (this.status == START)
return;
this.theThread = new Thread(new ThreadStart(this.StartThread));
this.theThread.Start();
this.status = START;
}
public void Stop()
{
if (this.theThread != null)
this.theThread.Abort();
this.status = STOP;
}
private void StartThread()
{
do
{
try
{
//do some work with HTTP requests
Thread.Sleep(1000 * 2);
}
catch (Exception e)
{
//retry - work forever
this.StartThread();
}
} while (this.status == START);
}
I suspect this is the problem:
private void StartThread()
{
do
{
try
{
//do some work with HTTP requests
Thread.Sleep(1000 * 2);
}
catch (Exception e)
{
//The recursive call here is suspect
//at the very least find a way to prevent infinite recursion
//--or rethink this strategy
this.StartThread();
}
} while (this.status == START);
}
When your app domain resets, you'll get a ThreadAbort exception which will be caught here and trigger a recursive call, which will hit another exception, and another recursive call. It's turtles all the way down!
Yes, making any change in web .config resets the application, and asp.net re-build the application.
Same is true for some other files like files under Bin and App_Code folders.