gpt4 book ai didi

c# - 在 C# 控制台应用程序中更改线程上下文

转载 作者:行者123 更新时间:2023-11-30 12:39:19 27 4
gpt4 key购买 nike

我有一个 C# 控制台应用程序,我可以在其中通过 TCP 套接字连接获取输入。当我通过套接字上的接收函数接收到输入时,如何切换到主线程?

与 WPF 中的类似内容非常相似:

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 2017DotNET 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", this, 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# - 在 C# 控制台应用程序中更改线程上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46862475/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com