Avatar of Frank Helk
Frank Helk
Flag for Germany asked on

How to share My.Settings in multiple application instances ?

Hi, friends,

I have written a (VB).NET console application that does external processing of some text information and is called repeatedly and often from a multithreaded application. Even while each instance runs only for a short time, it's possible that two instances run concurrently.

Unfortunately I observe crashes of the console application, and it rund flawless in the debugger with the same dataset. This behaviour seems to occur more often since I log more data ( = longer run time of each instance = more concurrent processes).

Due to my own convenience I've made use of the My.Settings facility for various program data. This data is updated from time to time by the console application, but it's no problem with what version of that data the application instance runs.

My suspicion is that parallel instances of the console application collide when accessing the application config file.

Unfortunately I don't see anything in the event log nor can I find any crash dump files ...

Any tip how to circumvent that problem ?
Visual Basic.NET.NET ProgrammingProgrammingR

Avatar of undefined
Last Comment
Paweł

8/22/2022 - Mon
Paweł

I'm not sure if i'm fully understanding you because my brain is kinda fried, if you're saying that you have more than one thread trying to update a file, then yes this is causing your problem, what you need to do is create a lock around the file to prevent more than one thread accessing it at one time.

if this is your problem, here's a little app i made for my blog to get the point across

using System;
using System.Linq;
using System.Threading;

namespace pc.ThreadLock
{
    enum Straw { Long, Short }
    class Straws
    {
        public int Count { get { return _straws.Count(); } }
        Straw[] _straws;

        public Straw this[int Index]
        {
            get
            {
                var pulledStraw = _straws[Index];

                //shift straws from pulled one left and resize array
                for (; Index + 1 < _straws.Length; Index++)
                    _straws[Index] = _straws[Index + 1];
                Array.Resize(ref _straws, _straws.Length - 1);

                return pulledStraw;
            }
        }

        public Straws(int NumOfStraws, int NumOfShortStraws = 1)
        {
            _straws = new Straw[NumOfStraws];

            while (NumOfShortStraws > 0)
            {
                //pick random index for short straw, if selected index
                //already has short straw, try again.
                var shortStrawIndex = Program.rnd.Next(NumOfStraws);
                if (_straws[shortStrawIndex] == Straw.Short)
                    continue;
                _straws[shortStrawIndex] = Straw.Short;
                NumOfShortStraws--;
            }
        }
    }

    class Program
    {
        public static Random rnd = new Random(DateTime.Now.Millisecond);
        static Straws Straws = new Straws(5, 2);

        //Our lock to prevent concurrent access to the straws object
        static object _lock = new object();

        static void Main(string[] args)
        {
            var Pawel = new Thread(PullStraw);
            Pawel.Name = "Pawel";

            var Magda = new Thread(PullStraw);
            Magda.Name = "Magda";

            var Jakub = new Thread(new ThreadStart(PullStraw));
            Jakub.Name = "Jakub";

            var Tomek = new Thread(new ThreadStart(PullStraw));
            Tomek.Name = "Tomek";

            var Marin = new Thread(new ThreadStart(PullStraw));
            Marin.Name = "Marin";

            var Threads = new Thread[] { Pawel, Magda, Jakub, Tomek, Marin };

            foreach (var t in Threads)
                t.Start();
        }

        static void PullStraw()
        {
            Straw PulledStraw;

            //restrict access to just one thread at a time
            lock (_lock)
            {
                PulledStraw = Straws[rnd.Next(Straws.Count - 1)];
            }

            var output = $"{Thread.CurrentThread.Name} pulled {PulledStraw.ToString()}";
            Console.WriteLine(output);
        }
    }
}

Open in new window

Frank Helk

ASKER
The problem is not threads but complete instances. The calling application is multithreaded (massive), and each thread could spawn an instance of my application ... and these multiple instances may  - I suspect - collide when  concurrently accessing My.Settings.
SOLUTION
Paweł

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER CERTIFIED SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Paweł

hi @frankhelk, i'm curious if you ever got this sorted and how.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Frank Helk

ASKER
Thanks for asking at the right time. Got it fixed yesterday, and it was something completely different.

My console process gets started from a service and therefore runs completely in the background. For debugging purposes I've had - besides of logging to a file - a instruction
[code]Console.WriteLine(...)[/code]
within my logging method. That worked very nice when running in VS, I could read all the logging output in the console window.

When running on the target machine, called from the service, there's no console window. Obviously (now) the output to stdout is buffered and diplayed in the console window asynchronous to the process. So that Console.WriteLine() instruction's output was stuffed into an internal buffer of (as I know now ....) 4k size. When that buffer got full, my process got deadlocked, waiting for the non-existent window to drain the buffer. Booom.

Due to the fact that this is not a real crash, I never got a message about a failure.

To nail that down I had to include a separate thread that waited for the process to hang and then logged a stack trace of the main thread. And even then I had to notice that the size of the text logged to file (which was written prior to writing to the console)  was just a bit more than 4k and a third look on the stack trace 'til I realized where the problem is.

A real nasty one.

Even while it was not your tip that led me to the final solution I award the points to you. Your tip was one thing I tried in between and it's a good advice for such sync problems.
Paweł

Oh man, that's rough, honestly i don't know if i'll ever have that problem, but i sure as hell wont forget the dangers of a console.writeline. and I appropriate the points.