2

I am attempting to run some fairly simple code in the Visual Studio immediate window. All the code does is read some JSON input, from a file, and uses that to call some other methods, for loading a database with values. Here's the code block:

using Newtonsoft.Json.Linq;
using System;
using System.IO;

namespace POST.API
{
    public class Initialization
    {
        public const string JSON_DATA_FILE = "C:\\OHA_SDD_POST_Development\\POST\\POST.API\\Services\\Setup\\InitializationData.json";
        public const string JSON_OBJKEY_DOMAIN = "Domain";
        public const string JSON_OBJKEY_ACCOUNTDOMAINTYPE = "AccountDomainType";
        public const string JSON_OBJKEY_ORGLOCTYPE = "OrganizationLocationType";

        public JObject POSTDataInitJObject;

        public JArray Domains;
        public JArray AccountDomainRoles;
        public JArray OrganizationLocationTypes;

        public API.Services.Domain SvcDomain;
        public API.Services.Organization SvcOrganization;
        public API.Services.Location SvcLocation;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="JsonDataFile"></param>
        public Initialization(string JsonDataFile = JSON_DATA_FILE)
        {
            string JsonData = File.ReadAllText(JsonDataFile);
            POSTDataInitJObject = JObject.Parse(JsonData);

            Domains = (JArray)POSTDataInitJObject[JSON_OBJKEY_DOMAIN];
            AccountDomainRoles = (JArray)POSTDataInitJObject[JSON_OBJKEY_ACCOUNTDOMAINTYPE];
            OrganizationLocationTypes = (JArray)POSTDataInitJObject[JSON_OBJKEY_ORGLOCTYPE];
        }
        /// <summary>
        /// 
        /// </summary>
        public void Load()
        {
            LoadDomains();
            LoadOrganizationLocationTypes();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Replace"></param>
        public void LoadDomains(bool Replace = true)
        {
            SvcDomain = new API.Services.Domain();

            if (Replace)
            {
                SvcDomain.ClearAllDomains(true);
            }

            foreach (var i in Domains)
            {
                SvcDomain.AddDomain(new API.Models.Domain
                {
                    Code = (string)i["Code"],
                    Definition = new API.Models.TypeDefinition
                    {
                        Name = (string)i["Name"],
                        Description = (string)i["Description"],
                        Order = Int32.Parse((string)i["Order"])
                    }
                });
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Replace"></param>
        public void LoadOrganizationLocationTypes(bool Replace = true)
        {
            SvcLocation = new API.Services.Location();

            if (Replace)
            {
                SvcLocation.ClearAllOrganizationLocationTypes();
            }

            foreach (var i in OrganizationLocationTypes)
            {
                SvcLocation.AddOrganizationLocationType(new API.Models.OrganizationLocationType
                {
                    Definition = new API.Models.TypeDefinition
                    {
                        Name = (string)i["Name"],
                        Description = (string)i["Description"],
                        Order = Int32.Parse((string)i["Order"])
                    }
                });
            }
        }
    }
}

I can successfully instantiate the object in the immediate window, but when I then try to call that Load() method, on that instance, I get:

A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

Evaluation requires a thread to run temporarily. Use the Watch window to perform the evaluation.

I've alraedy turned off Options -> Debug -> Enable property evaluation and other implicit function calls.

Got me stumped... Seems super simple, and I totally can't get past it.

Michael Doleman
  • 522
  • 2
  • 9
  • 24
  • May I know why you want to do this in the immediate window? – CodingYoshi Feb 13 '17 at 23:00
  • are you trying to troubleshoot an error? or make sure the JSON contents are being loaded properly? – Eric Walter Feb 13 '17 at 23:01
  • So, the reason for wanting to run in an immediate window is because the code is one-time use. I.e., it's only used to initialize some things upon set-up of a new database. So I have no facilities set-up for calling it from anywhere else. I mean, I could set-up a console app. to target it, I suppose, but was just trying to avoid that. And in testing it I need to run it a lot, so it's easiest to do that from the immediate window. – Michael Doleman Feb 14 '17 at 00:05

3 Answers3

4

You are calling some code directly or indirectly that has this in it:

System.Diagnostics.Debugger.NotifyOfCrossThreadDependency()

Why would the code have that?

Some of you might have ran into this situation where you try to evaluate a property or a method during debug time, and get this message in the value cell of the watch:
enter image description here

There is a quick “workaround” to this issue. If you look carefully, you will see a small round icon after the message: enter image description here

Pressing on this icon will force the evaluation to continue, which most likely will give you the result you were after:
enter image description here

When we break the debugger and try to evaluate a property which requires running code, we can only run code in the current thread. All other threads are frozen to minimize the system state impact… But, what if my property requires another thread to run in order to complete evaluation? For example, if I am doing a remote call, I will most likely need the ThreadPool threads for that… But all other threads are frozen… which will result in a “deadlock”. The debugger has a protection measure against that, which gives a max of 5 seconds to the evaluation code to run. If the code did not finish to run within the time limit, For example, when we are blocked due to a frozen thread, the watch will be “hanged” for 5 seconds, and after that evaluation will be aborted. We will get this message to notify us of the problem: enter image description here

So that line of code causes the message you are getting:

The debugger will not allow it automatically, to avoid state changes, and instead, will give the user the “The function evaluation requires all threads to run” message.

If you have the debugger open, then:

If the user decides it’s OK to let all threads run, he can push the icon next to the message, which will cause the debugger to run the property code a second time, this time with all threads running, and not aborting on the NotifyOfCrossThreadDependency method.

Please read this article for more details.

Also, I am not sure what your reasoning is to run all that code in the immediate window. Perhaps you can write a small console application and run the app instead.

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
0

So, it looks like the problem was an incidental one. I had simply failed to give a reference in the project, from which I was trying to run the code, to EntityFramework. Not sure why it would've thrown the error such as that given, but that's what happened. Seems odd to me, but I'll take it. It works now.

Michael Doleman
  • 522
  • 2
  • 9
  • 24
0

General comment: The immediate window is very much needed to evaluate code. Not simple applications but ones that require you, for example to step into a website and with the use of Selenium evaluate objects. It would be time consuming, but not impossible, to create a console application for a workaround to something we have always been able to use, which is to evaluate objects using the immediate window. I'll take my chances on window state.

Randy
  • 1