Custom task runner method throws ArgumentException - c#

Because of the fact that CultureInfo is not being copied from thread to thread I have made following method to do that thing for me.
public static StartCustomTask(Action action, TaskCreationOptions tco = TaskCreationOptions.None)
{
var currentCult = Thread.CurrentThread.CurrentCuture;
var currentUiCult = Thread.CurrentThread.CurrentUICulture;
return Task.Factory.StartNew(() =>
{
Thread.CurrentThread.CurrentCuture = currentCult;
Thread.CurrentThread.CurrentUICulture = currentUiCult;
action();
}, tco);
}
basically this code copies culture info from current thread to the thread that is gonna execute the action. I don't know why but it throws System.ArgumentException saying Value does not fall within the expected range. I've tried to run the action itself regularly on the main thread and it goes perfectly. By that I mean, that method that is being an action does not have a problem itself there is a problem somewhere in the code above I guess.
here is the stack trace of an exception
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)
at System.Web.HttpRequest.BuildUrl(Func`1 pathAccessor)
at System.Web.HttpRequest.get_Url()
at SL.CoreLogic.Web.FrontEnd.Controllers.AccountController.<>c__DisplayClass37.<ResetPassword>b__31() in d:\CoreProjects\CoreLogic\CoreLogic-RusSlot\SL.CoreLogic\SL.CoreLogic.Web.FrontEnd\Controllers\AccountController.cs:line 447
at SL.CoreLogic.Common.CustomTask.<>c__DisplayClass1.<StartWithCurrentCulture>b__0() in d:\CoreProjects\CoreLogic\CoreLogic-RusSlot\SL.CoreLogic\SL.CoreLogic.Common\CustomTask.cs:line 22
at System.Threading.Tasks.Task.
and one more thing. this code was working perfectly but all of a sudden it started doing this.

I got it. the problem was that the action contained a line like this Url = Request.Url, as I guess at the time code was being executed the Request object did not exist or was not set.

Related

InvalidOperationException "NoGCRegion mode was already in progress" on call to GC.TryStartNoGCRegion

I'm doing performance testing comparing various algorithms and want to eliminate the scatter in the results due to garbage collection perhaps being done during the critical phase of the test. I'm turning off the garbage collection using GC.TryStartNoGCRegion(long) (see https://learn.microsoft.com/en-us/dotnet/api/system.gc.trystartnogcregion?view=net-6.0) before the critical test phase and reactivating it immediately afterwards.
My code looks like this:
long allocatedBefore;
int collectionsBefore;
long allocatedAfter;
int collectionsAfter;
bool noGCSucceeded;
try
{
// Just in case end "no GC region"
if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
{
GC.EndNoGCRegion();
}
// Exception is thrown sometimes in this line
noGCSucceeded = GC.TryStartNoGCRegion(solveAllocation);
allocatedBefore = GC.GetAllocatedBytesForCurrentThread();
collectionsBefore = getTotalGCCollectionCount();
stopwatch.Restart();
doMyTest();
stopwatch.Stop();
allocatedAfter = GC.GetAllocatedBytesForCurrentThread();
collectionsAfter = getTotalGCCollectionCount();
}
finally
{
// Reactivate garbage collection
if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
{
GC.EndNoGCRegion();
}
}
//...
private int getTotalGCCollectionCount()
{
int collections = 0;
for (int i = 0; i < GC.MaxGeneration; i++)
{
collections += GC.CollectionCount(i);
}
return collections;
}
The following exception is thrown from time to time (about once in 1500 tests):
System.InvalidOperationException
The NoGCRegion mode was already in progress
bei System.GC.StartNoGCRegionWorker(Int64 totalSize, Boolean hasLohSize, Int64 lohSize, Boolean disallowFullBlockingGC)
bei MyMethod.cs:Zeile 409.
bei MyCaller.cs:Zeile 155.
The test might start a second thread that creates some objects it needs in a pool.
As far as I can see, the finally should always turn the GC back on, and the (theoretically unnecessary) check at the beginning should also do it in any case, but nevertheless, there is an error that NoGCRegion was already active.
The question C# TryStartNoGCRegion 'The NoGCRegion mode was already in progress' exception when the GC is in LowLatency mode got the same error message, but there was clear code path to have activated NoGCRegion more than once there. I can't see how that could happen here.
The test itself is not accessing GC operations except for GC.SuppressFinalize in some Dispose() methods.
The test itself does not run in parallel with any other test; my Main() method loops over a set of input files and calls the test method for each one.
The test method uses an external c++ library which would be unmanaged memory in the .NET context.
What could be causing the exception, and why doesn't the call to GC.EndNoGCRegion(); prevent the problem?

System.Runtime.InteropServices.SEHException in UnityEngine.dll

I am importing unity3D project for windows phone 8. and adding few lines of code which interact the c# code to the event changing handler of Object(SphereScript) in unity3D.
var sphereScript = UnityEngine.Object.FindObjectOfType<SphereScript>();
sphereScript.SphereStateChanged += sphereScript_SphereStateChanged;
sphereScript_SphereStateChanged(sphereScript.IsSphereMoving);
The project compiled fine with no errors but when it runs on phone it gives an error on line
UnityEngine.Object.FindObjectOfType<SphereScript>();
An exception of type 'System.Runtime.InteropServices.SEHException' occurred in UnityEngine.DLL but was not handled in user code. i don't know why this error occurs. but first time when i started the project it asked me to locate the file name UnityEngineObject.cs. Where can i find this file or how can i solve the problem. Thanks.
Url for complete code http://docs.unity3d.com/Manual/wp8-unity-interaction.html
Exception details:
System.Runtime.InteropServices.SEHException was unhandled by user code
HResult=-2147467259
Message=External component has thrown an exception.
Source=UnityEngine
ErrorCode=-2147467259
StackTrace:
at UnityEngine.Internal.$Calli.Invoke38(Int32 arg0, IntPtr method)
at UnityEngine.Object.FindObjectsOfType(Type type)
at UnityEngine.Object.FindObjectOfType(Type type)
at UnityEngine.Object.FindObjectOfType[T]()
at UnityXamlInteractionExample.MainPage.Unity_Loaded()
InnerException:
in Unity 5x i had equal the problem.
So try this:
In script SphereScript.cs:
re-write this:
public event Action<bool> SphereStateChanged;
to this:
public static event Action<bool> SphereStateChanged = delegate { };
next, in Visual Studio after build project un-comment these parts of code:
UnityApp.SetLoadedCallback(() => { Dispatcher.BeginInvoke(Unity_Loaded); });
private void Unity_Loaded() { }
now insert into private void Unity_Loaded() this:
ShareScript.SphereStateChanged += SphereStateChanged;
and finally add this:
void SphereStateChanged(bool currentSpehreState)
{
Dispatcher.BeginInvoke(() =>
{
SphereStateTextBlock.Text = currentSpehreState ? "Spehre is moving" : "Sphere is stopped";
});
}
Good luck, bye :)

ASP.NET ThreadPool.QueueUserWorkItem Common.Logging to NLog crashes IIS - Bug or just me?

I have a long-running asynchronous task that is kicked off from an ASP.NET MVC4 web page. The controller method looks like this:
[HttpPost]
public ActionResult Index(IndexModel model)
{
if (ModelState.IsValid)
{
try
{
model.NotificationRecipient = model.NotificationRecipient.Replace(';', ',');
ImportConfiguration config = new ImportConfiguration()
{
BatchId = model.BatchId,
ReportRecipients = model.NotificationRecipient.Split(',').Select(c => c.Trim())
};
System.Threading.ThreadPool.QueueUserWorkItem(foo => LaunchFileImporter(config, this.HttpContext.ApplicationInstance.Context));
if (model.RunExport) ThreadPool.QueueUserWorkItem(foo => LaunchFileExporter());
Log.InfoFormat("Queued the ImportProcessor to process invoices. Send Notification: {0} Email Recipient: {1}",
model.SendNotification, model.NotificationRecipient);
TempData["message"] = "The import processor job has been started.";
//return RedirectToAction("Index", "Home");
}
catch (Exception ex)
{
Log.Error("Failed to properly queue the invoice import job.", ex);
ModelState.AddModelError("", ex.Message);
}
}
var dirInfo = new System.IO.DirectoryInfo(dir);
model.Files = dirInfo.EnumerateFiles("*.xml").OrderBy(x => x.Name.ToLower());
return View(model);
}
My LaunchFileImporter method looks like this:
private void LaunchFileImporter(ImportConfiguration config, System.Web.HttpContext context)
{
//the semaphore prevents concurrent running of this process, which can cause contention.
Log.Trace(t => t("submitter semaphore: {0}", (exporter == null) ? "NULL" : "present."));
submitter.WaitOne();
try
{
Log.Trace(t => t("Context: {0}", context));
using (var processor = new ImportProcessor(context))
{
processor.OnFileProcessed += new InvoiceFileProcessing(InvoiceFileProcessingHandler);
processor.OnInvoiceProcessed += new InvoiceSubmitted(InvoiceSubmittedHandler);
processor.Execute(config);
}
}
catch (Exception ex)
{
Log.Error("Failed in execution of the File Importer.", ex);
}
submitter.Release();
}
My Logger is a Common.Logging private static readonly ILog, and is configured for NLog. It seems properly wired up; at least, I get a fair amount of logs out of it.
Here's the thing: The moment I hit System.Threading.ThreadPool.QueueUserWorkItem, the application pool death spirals into a silent death, resetting the app pool, reloading the membership provider, reprocessing the web.config, the whole shebang... No YSOD, no indication on the web page... everything just quietly blows up. The last log entry I get is Queued the ImportProcessor to process invoices....
I should note the page does the refresh. The TempData["message"] is populated and displayed on the screen, which makes me believe the problem is happening in the asynchronous process... but pretty much immediately. Due to the lack of additional logs I am assuming there is a problem with the logger.
So I'm hoping someone can either tell me what is happening, point to some documented issue with this, tell me how I'm being an idiot, or reproduce something similar as a bug.
Thanks!
UPDATE
#RichardDeeming pointed out that the context information was not getting into the spawned thread, and this seemed to be the cause of the problem. I still haven't wrapped my brain around why this didn't work nor did it write the trace messages, but once I captured the part of the context that I needed, the IPrincipal, and used that instead of the context object, it just worked.
You'll get a NullReferenceException in the line:
ThreadPool.QueueUserWorkItem(foo => LaunchFileImporter(config, HttpContext.ApplicationInstance.Context));
The HttpContext gets cleaned up once the request has completed. Since the exception is thrown on a background thread, it will bring down the whole AppDomain, causing your application to restart.
You need to capture the relevant state from the context in the controller action, and use that state in the WaitCallback delegate:
IPrincipal user = Context.User;
ThreadPool.QueueUserWorkItem(foo => LaunchFileImporter(config, user));
// Or:
// ThreadPool.QueueUserWorkItem(state => LaunchFileImporter(config, (IPrincipal)state);

NullReferenceException on if statement with only a bool check

I'm experiencing a "strange" situation with a live ASP.NET MVC 3 app. The error start on production after X hours of use. I did not have been able to reproduce the error on my development machine.
Here is my controller action signature:
[HttpPost]
public ActionResult AddBanking(int id, int? page, int bankId,
string q, int? searchFlag, string query, string accountNo,
string accountManager, bool? personnal, int? branchId,
int? selectedId, BankSearchModel data)
The basic idea is that the controller is use for two forms on the View, one for searching where searchFlag is a Hidden field and another form for adding, here is a basic code structure.
try
{
if (searchFlag.HasValue)
{
var vm = svc.FetchBanks(bankId, q);
return View(vm);
}
else
{
bool valid = true, isIndividu = false;
// some code
if(!valid) // <- this is where the line 106 is
{
}
}
}
catch(Exception ex)
{
ex.Data.Add("context", "AddBanking - THIS IS IT");
Log.Error(ex);
return RedirectToAction("Error", new { id = 0 });
}
The error occurs after long periods of time the app run flawlessly, all of a sudden, that exception is caught, but when the users submit the first form (for searching -> searchFlag = 1), so in my example it entered the first if statement.
This is the error and stack trace
context: AddBanking - THIS IS IT
Message: Object reference not set to an instance of an object.
Stack:
at XYZ.Controllers.BanksController.AddBanking(Int32 id, Nullable`1 page, Int32
bankId, String q, Nullable`1 searchFlag, String query, String accountNo, String
accountManager, Nullable`1 personnal, Nullable`1 branchId, Nullable`1 selectedId,
BankSearchModel data) in E:\Projects\XYZ\ABC\123.Web\Controllers\BanksController.cs:line
106
How can it be possible to throw exception on a if statement with a non-nullable bool ?
Since there is a return View() in my first if block, and I'm 100 % certain it entered there how come the exception is on the line 106 where the execution should not even go there.
This is something that happen only after long period of production time, yesterday (8 to 5) this process worked, and this morning bang the exception is throwing, but only in production (Windows 2008, ASP.NET MVC 3). From my developement machine with the same database and same data posting to the page is working.
My main question, how am I suppose to debug this, at first I thought that the stack trace does not returned the right line number, so I added a try/catch inside the action, yet it still return the if(!valid) as NRE...
I would appreciate any idea / guide line. Of course I could separate the two process inside the action and it might fix the problem, but I would rather like to understand what I'm doing wrong in the example.
Edit: I'm completely clueless
By the time I asked this question, the page worked without any change in code and for the exact same data posted.
Edit 2 # 10:30 2011/06/01
Thanks for your suggestions, but I'm really thinking this is really something harder to find. The bug did re-appear today but the app was working from 1 hour after I post this question yesturday until today # 10 am.
Here is more detail on what I've done so far to try to understand what's going on:
I've rebuilt the app (no code changes, and re-deploy bin, views) with .pdb files.
I've put try/catch on every path that the execution should take here is the exact scenario:
View:
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<fieldset>
#Html.Hidden("searchFlag", 1)
#Html.Textbox("q")
<input type="submit" value="Chercher" /></td>
</fieldset>
}
svc cannot be null because I have it set on the controller like this:
[Authorize]
public class BanksController : BaseController
{
BankService svc = new BankService();
...
}
The FetchBanks method
public BankSearchModel FetchBanks(int bankId, string query)
{
return Execute<BankSearchModel>(db =>
{
try
{
// some linq stuff
}
catch(Exception ex)
{
XYZ.Log.Error(ex); // <= note1
}, "Error returned by Execute");
}
My Execute method
protected static T Execute<T>(Func<XYZDbContext, T> query, string errorMessage, bool deferredLoading)
{
try
{
using (XYZDbContext db = new XYZ...())
{
#if DEBUG
db.Log = new DebuggerWriter();
db.CommandTimeout = 3 * 60;
#endif
if (!deferredLoading)
db.DeferredLoadingEnabled = false;
return query(db);
}
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine(ex.Message + "\r\n" + ex.StackTrace.ToString());
throw;
#else
ex.Data.Add("context", "Manager, executing query");
XYZ.Log.Error(ex);
return default(T);
#endif
}
}
So again, I understand that the line 106 is not the real error here, but I have try/cath in every single method that the execution should go when the searchFlag is set to 1 (from the first form of the view. Still the only Log.Error(ex) I got was the one telling me there is an error on my contorller at line 106.
Note1 If the error would have come from the FetchBanks method it would have entered the catch inside that method and send me and email with stack trace of that method.
At the end of my FetchBanks I return a BankSearchModel which as all List so all databases query are executed before returning to the controller.
And again, how can it work for the same data posted all day long and suddently stop working. Would that be possible that the signature of the controller with all my null object would cause that behaviour?
This is the only email I got after adding try/catch everywhere that should have send me an error. i.e no other method are entering their catch (The execute, the FetchBanks) only the controller action. I would really like to understand what's going on.
New error occured at 6/1/2011 9:48:13 AM
context: AddBanking - THIS IS IT
Message: Object reference not set to an instance of an object.
Stack:
at XYZ.Web.Controllers.BanksController.AddBanking(Int32 id, Nullable`1 page, Int32
bankId, String q, Nullable1 searchFlag, String query, String accountNo, String
accountManager, Nullable1 personnal, Nullable1 branchId, Nullable1 selectedId,
BankSearchModel data) in
E:\Projects\HiddenForObiousReason\Controllers\BanksController.cs:line 106
After separating my action into two disctinct action (for the two forms in the view) I discover that the errors was relating to the second form and related to the validation of the Model passed.
Here are my two actions now:
[HttpPost]
public ActionResult AddBanking(int id, int? page, int bankId, string q)
[HttpPost]
public ActionResult CreateBanking(int id, int? page, int bankId, string query, string
accountNo, string accountManager, bool? personnal,
int? branchId, int? selectedId, BankSearchModel data)
The error was thrown when the first form was posted, but the Html.ValidationSummary was not writing any errors to the view. After separating the action no error were thrown on the first form, but only on the second and now the ValidationSummary is writing to the View. That is normal and I understand that the first form now do not validate the Model.
What I still cannot fully understand exactly why the error was raising on batch of 15 minutes once a day (from 8am to 5pm). If someone has explanation I would appreciate it. Why a form post with the exact same data works and later do not work (the two posts were supposed to fail since the Model Validation was the cause of the error).
That was probably my mistake to have 1 action for two distinct functionality.
To debug this, check the objects for null.
I wouldn't worry about line 106 so much, check the object(s) in the code for null.
Example:
if (svc == null)
{
Log.Error(new Exception("svc is null!");
}
You have lots of strings in that method call, strings default to null if they are unassigned, so that could be a source of the error as well.

Preventing Subsequent Invoke requirements within cross-thread invokes

I've got a cross thread invoke going on, and the invoke works fine, however I have found that all subsequent function calls need to be invoked aswell, otherwise it throws exceptions, how do I go about either modifiying my invoke command, or through some other solution, fix this?
This is my current invoker:
foreach (chat_window oc in open_chats)
{
if (oc.Name == friend)
{
string updmsg = msg.Substring(msg.IndexOf('\n')).Trim();
string[] argNames = new string[2];
argNames[0] = friend;
argNames[1] = updmsg;
Type t = oc.GetType();
t.InvokeMember("updateChat",
System.Reflection.BindingFlags.InvokeMethod, null, oc, argNames);
}
}
Thanks in advance, Psy
I assmue that chat_window is some WinForms object derived from Control?
If so then you probably want to use Control.Invoke/Control.BeginInvoke in order to marshall the call back to the UI thread.
oc.Invoke(oc.updateChat, argNames);

Categories