Jump to content

C# Execute code on main thread from hyperthread

Guest
Go to solution Solved by Guest,
26 minutes ago, Mira Yurizaki said:

snip

I recall seeing a bit about Invoke but just as confused on how to use it.

I ended up using a single flag as I thought of a way that wasn't ueber complex.

As I have about 15~ UI elements that get toggled, I thought I'd have a lot to deal with but I just use 1 boolean & then call that function if it's true & set it (the bool) to false again.

TL;DR

I need to change the value of a variable in the main thread, but only know the status in a separate thread. What command do I use to call a method from a thread to be executed in the main thread?

 

Long:

I'm working with Threads & running a server/client on a separate thread (as was recommended by YouTube U)

In Unity, you cannot change certain variables from a thread (All physics & stuff run on the main thread).

When the connection is established, I try to enable the game screen through the server thread. I get an error that prevents me from enabling the in game screen however.

I tried putting the server in the main thread, but the program freezes/acts unexpectedly. (Putting a while loop that's always true does that sometimes)

 

Someone told me about callbacks & lambda functions but I'm not exactly sure how to use them because the articles I found online were quite vague. (Y'know like when a dictionary uses the word it's defining in the definition?)

I've considered flags, and might go for that. However I'd like a more elegant solution as I feel I could use this knowledge in future projects.

Link to comment
Share on other sites

Link to post
Share on other sites

22 minutes ago, geo3 said:

What version of unity?

2018 or 2019. It was newest like a month ago. 

22 minutes ago, geo3 said:

AFAIK Unity doesn't fully support multi-threading from within scripts in the current release version. 

C# supports it though. 

I posed the question on a game development board & some people noted that certain things like physics & rendering are commonly locked to a single thread to prevent parallelism problems.

 

For example: Race conditions. 

Link to comment
Share on other sites

Link to post
Share on other sites

7 minutes ago, fpo said:

C# supports it though. 

I posed the question on a game development board & some people noted that certain things like physics & rendering are commonly locked to a single thread to prevent parallelism problems.

Yeah but I think you will have issues trying it with in the framework of unity.

I believe scripts are run in their own (single) thread, separate from physics and rendering threads, but still just one.

Unity ECS has multi-threading scripts, but that's still in beta.

Link to comment
Share on other sites

Link to post
Share on other sites

Last I worked with data sharing across threads, I created a custom event and had the other thread listen to it. Though that was years ago and I don't remember what I did exactly, so I'll let Stack Exchange come to the rescue: https://stackoverflow.com/questions/2403972/c-sharp-events-between-threads-executed-in-their-own-thread-how-to

Link to comment
Share on other sites

Link to post
Share on other sites

26 minutes ago, Mira Yurizaki said:

snip

I recall seeing a bit about Invoke but just as confused on how to use it.

I ended up using a single flag as I thought of a way that wasn't ueber complex.

As I have about 15~ UI elements that get toggled, I thought I'd have a lot to deal with but I just use 1 boolean & then call that function if it's true & set it (the bool) to false again.

Link to comment
Share on other sites

Link to post
Share on other sites

            public static Task<Task<T>>[] Interleaved<T>(IEnumerable<Task<T>> tasks)
            {
                var inputTasks = tasks.ToList();

                var buckets = new TaskCompletionSource<Task<T>>[inputTasks.Count];
                var results = new Task<Task<T>>[buckets.Length];
                for (int i = 0; i < buckets.Length; i++)
                {
                    buckets[i] = new TaskCompletionSource<Task<T>>();
                    results[i] = buckets[i].Task;
                }

                int nextTaskIndex = -1;
                Action<Task<T>> continuation = completed =>
                {
                    var bucket = buckets[Interlocked.Increment(ref nextTaskIndex)];
                    bucket.TrySetResult(completed);
                };

                foreach (var inputTask in inputTasks)
                    inputTask.ContinueWith(continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

                return results;
            }

	    //Example usage
            foreach (var task in Interleaved(tasks))
            {
                Task<T> t = await task;
                T result = await t;
    
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
                {
                    SpecificLargeProcessingHere(result.thing);
                }), null);
            }

This might be a bit overkill but I've used this before when I've had to crunch a lot of tasks as once.

It process all items pretty much at the same time.

 

Found this on https://blogs.msdn.microsoft.com/pfxteam/2012/08/02/processing-tasks-as-they-complete/

 


 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×