0

I have this piece of code which is always throwing a null ref exception even if the variable is not null and I can see its value:

httpClient.DownloadDocumentML(req)
   .ContinueWith(t =>
   {
       string x = t.Result.Document.DocumentData;
       byte[] arrayFile = Encoding.ASCII.GetBytes(x);
       byteArrays.Add(arrayFile);                     
       t.Wait();
       trash = byteArrays;
       Session["multipleFiles"] = byteArrays;                           
       //return Json("multiple");
   });

The bytearrays variable is alywas throwing null ref exception but its value is not null.

Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
Haytham
  • 744
  • 1
  • 9
  • 24
  • at this instruction "Session["multipleFiles"] = byteArrays;" – Haytham Apr 23 '18 at 08:53
  • 2
    So most likely `Session` is null. – Uwe Keim Apr 23 '18 at 08:53
  • Session object is most probably null https://stackoverflow.com/questions/10536136/why-does-session-object-throws-a-null-reference-exception – Razvan Dumitru Apr 23 '18 at 08:55
  • 1
    Nobody can help you with this question as much as your debugger can. – Sefe Apr 23 '18 at 08:55
  • I debugged the code when i check the value of the "byteArrays" variable it is not null , i don't know why when i try to put the value of "byteArrays" which is not null into the session variable it throws a NRE – Haytham Apr 23 '18 at 08:58
  • *Why* are you using `ContinueWith` instead of async/await? Are you sure `Session` is still available in the new thread? That's what `await` does - ensure the original synchronization context is restored. Why convert a string to *bytes* using the ASCII encoding? Is `byteArrays` even initialized? – Panagiotis Kanavos Apr 23 '18 at 08:59
  • @Haytham there are quite a few strange things with this code. 1) `ContinueWith` could lead to a missing Session. 2) Converting strings to ANSI bytes without reason could lead to conversion errors, never mind the memory waste of discarding a string only to create another similar buffer.3) `t.Wait()` is 100% pointless - `.t.Result` already blocks, besides the `ContinueWith` would only be called if the task already completed. 4) What is `trash` and what are you doing with it? That variable *still* references the original List (can't be an array despite the name) – Panagiotis Kanavos Apr 23 '18 at 09:03
  • @Haytham the problem is not with byteArrays but with the Session object which may be null. – disklosr Apr 23 '18 at 09:05
  • @Haytham in short why not write `var result=await httpClient.DownloadDocumentML(req); var dataList=(List)Session["whatever"] ?? new List(); dataList.Add(result.Result.Document.DocumentData);` ? – Panagiotis Kanavos Apr 23 '18 at 09:06
  • Panagiotis Kanavos cannot use "await" because the project I am working on uses .NET 4.0 – Haytham Apr 23 '18 at 09:13
  • @Haytham update the question with all the relevant information then, including the stack you use - Webforms, MVC? BTW 4.0 is no longer supported, the earliest supported vesion is 4.5.2. And you *can* use `async/await` with the Bcl.Async package. Finally, if you use 4.0 are you *sure* the `Session` flows from one thread to the other or that you can even make asynchronous calls like that without extra configuration like setting the `Async` directive on the page, or registering the asynchronous task? I can't remember what it was like 8 years ago. – Panagiotis Kanavos Apr 23 '18 at 09:57
  • @Haytham read Scott Hansleman's [The Magic of using Asynchronous Methods in ASP.NET 4.5 plus an important gotcha](https://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx) and listen to the podcast [Everything .NET programmers know about Asynchronous Programming is wrong](https://hanselminutes.com/327/everything-net-programmers-know-about-asynchronous-programming-is-wrong). None of these techiques is required nowadays but if you target .NET 4.0 you need them. – Panagiotis Kanavos Apr 23 '18 at 10:00
  • @Haytham besides, if you are in 4.0 you *will* block eventually in order to return something to the client. *Don't* handle the Session or any global/static objects until *after* the block. Modify your code to receive all it needs as parameters and return all the data it generates/modifies as results of the final task. That's just good coding practice anyway. – Panagiotis Kanavos Apr 23 '18 at 10:03
  • @Haytham finally, `async/await` in ASP.NET is meant to save threads while awaiting for asynchronous operations to complete, not execute stuff in parallel. Every request gets its own thread already. Since you *have* to block, you won't get any benefit from `ContinueWith` unless you execute more async operations in the continuations. If you only make one remote call, you might as well block while waiting with `var result=httpClient.DownloadDocumentML(req).Result;' – Panagiotis Kanavos Apr 23 '18 at 10:05

0 Answers0