C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在C#console应用程序中更改线程上下文大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个C#控制台应用程序,其中我可以通过TCP套接字连接获得输入.当我通过套接字通过接收功能接收输入时,如何切换到主线程?

在@L_675_5@中类似于这样的东西:

public void TaskDispatcher()
{
    if (DispatcherObjectForTaskDispatcher.Thread != System.Threading.Thread.CurrentThread)
        DispatcherObjectForTaskDispatcher.Invoke(new TaskDispatcherDelegate(TaskDispatcher));
    else
    {
        // Do some thing in the UI thread
    }
}

解决方法

只需使用 Producer-Consumer模式,如下面的工作示例所示.从其他线程入队作业,让主线程处理作业队列中的排队作业.

我使用了一个计时器线程和一个用户输入线程来模拟生成作业的2个线程.您可以实现TCP事件,以便在作业队列中排队作业.您应该将任何相关对象作为参数存储在作业中,以便以后处理.您还必须定义要由作业调用函数,该函数将在主线程中运行.

这里使用的主要线程只是为了使作业出列并处理它们,但是如果你稍微改进一下这个代码就可以使用任何其他线程来实现这个目的.

您甚至可以实现多线程处理,其中更多处理线程从同一作业队列中出列.请注意,这会带来您可能需要处理的新并发问题.这是在您的应用程序中获得更多处理能力的缺点.一些场景适用于多线程处理(例如视频/图像处理)而另一些场景则不适用.

下面的代码一个完整的工作示例,用Visual studio 2017,DotNET 4.6.1,控制台应用程序项目编写.只需复制,粘贴并点击F5即可.

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;

// Compiled and tested in: Visual studio 2017,DotNET 4.6.1

namespace MyNamespace
{
    public class Program
    {
        public static void Main(String[] args)
        {
            MyApplication app = new MyApplication();
            app.Run();
        }
    }

    public class MyApplication
    {
        private BlockingCollection<Job> JobQueue = new BlockingCollection<Job>();
        private CancellationTokensource JobCancellationTokensource = new CancellationTokensource();
        private CancellationToken JobCancellationToken;
        private Timer Timer;
        private Thread UserInputThread;



        public void Run()
        {
            // Give a name to the main thread:
            Thread.CurrentThread.Name = "Main";

            // Fires a Timer thread:
            Timer = new Timer(new TimerCallBACk(TimerCallBACk),null,1000,2000);

            // Fires a thread to read user inputs:
            UserInputThread = new Thread(new ThreadStart(ReadUserInputs))
            {
                Name = "UserInputs",IsBACkground = true
            };
            UserInputThread.Start();

            // Prepares a token to cancel the job queue:
            JobCancellationToken = JobCancellationTokensource.Token;

            // Start processing jobs:
            ProcessJobs();

            // Clean up:
            JobQueue.Dispose();
            Timer.Dispose();
            UserInputThread.abort();

            Console.WriteLine("Done.");
        }



        private void ProcessJobs()
        {
            try
            {
                // checks if the blocking collection is still up for dequeueing:
                while (!JobQueue.IsCompleted)
                {
                    // The following line blocks the thread until a job is available or throws an exception in case the token is cancelled:
                    JobQueue.Take(JobCancellationToken).Run();
                }
            }
            catch { }
        }



        private void ReadUserInputs()
        {
            // User input thread is running here.
            ConsoleKey key = ConsoleKey.Enter;

            // Reads user inputs and queue them for processing until the escape key is pressed:
            while ((key = Console.ReadKey(true).Key) != ConsoleKey.EscapE)
            {
                Job userInputJob = new Job("UserInput",this,new Action<ConsoleKey>(ProcessUserInputs),key);
                JobQueue.Add(userInputJob);
            }
            // Stops processing the JobQueue:
            JobCancellationTokensource.Cancel();
        }

        private void ProcessUserInputs(ConsoleKey key)
        {
            // Main thread is running here.
            Console.WriteLine($"You just typed '{key}'. (Thread: {Thread.CurrentThread.NamE})");
        }



        private void TimerCallBACk(object param)
        {
            // Timer thread is running here.
            Job job = new Job("TimerJob",new Action<String>(ProcessTimer),"A job from timer callBACk was processed.");
            JobQueue.TryAdd(job); // Just enqueues the job for later processing
        }

        private void ProcessTimer(String messagE)
        {
            // Main thread is running here.
            Console.WriteLine($"{messagE} (Thread: {Thread.CurrentThread.NamE})");
        }
    }



    /// <sumMary>
    /// The Job class wraps an object's method call,with or without arguments. This method is called later,during the Job execution.
    /// </sumMary>
    public class Job
    {
        public String Name { get; }
        private object TargetObject;
        private Delegate Targetmethod;
        private object[] Arguments;

        public Job(String name,object obj,Delegate method,params object[] args)
        {
            Name = name;
            TargetObject = obj;
            Targetmethod = method;
            Arguments = args;
        }

        public void Run()
        {
            try
            {
                Targetmethod.Method.Invoke(TargetObject,Arguments);
            }
            catch(Exception eX)
            {
                Debug.WriteLine($"Unexpected error running job '{name}': {ex}");
            }
        }

    }
}

大佬总结

以上是大佬教程为你收集整理的在C#console应用程序中更改线程上下文全部内容,希望文章能够帮你解决在C#console应用程序中更改线程上下文所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。