Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不使用队列的情况下将对象传递给不同的线程_C#_Multithreading - Fatal编程技术网

C# 在不使用队列的情况下将对象传递给不同的线程

C# 在不使用队列的情况下将对象传递给不同的线程,c#,multithreading,C#,Multithreading,我目前正在尝试编写一个多线程WPF c应用程序,以便UI和其他模块从一开始就在各自的线程上运行 然而,例如,如果我想将一个对象从UI传递到一个模块,我想确保UI不必等待任何东西,并且可以立即继续。因此,在这种情况下,使用队列并不像其他帖子所建议的那样起到安静的作用 对我能做这件事有什么建议吗?我正在考虑使用一个接口类来连接两个线程,或者使用一个易失性变量来保存对象,等等。但是这些听起来都不是很有效。谢谢你可以用它来做。这是一个如何使用它的例子。希望有帮助。我认为不使用队列的理由并不可靠。您必须确

我目前正在尝试编写一个多线程WPF c应用程序,以便UI和其他模块从一开始就在各自的线程上运行

然而,例如,如果我想将一个对象从UI传递到一个模块,我想确保UI不必等待任何东西,并且可以立即继续。因此,在这种情况下,使用队列并不像其他帖子所建议的那样起到安静的作用


对我能做这件事有什么建议吗?我正在考虑使用一个接口类来连接两个线程,或者使用一个易失性变量来保存对象,等等。但是这些听起来都不是很有效。谢谢

你可以用它来做。这是一个如何使用它的例子。希望有帮助。

我认为不使用队列的理由并不可靠。您必须确保将锁定的代码/时间降至最低

我为此编写了一个很好的类,它也支持批处理。您可以查看它,并可能会从中获得灵感:

WorkerThread:

用法:


你没有解释你想做什么,所以很难给出具体的答案。在后台运行一些繁重的工作以避免阻塞UI描述了一半的并发问题。另一半是为了避免在服务器需要很长时间才能应答时长时间等待

如果要执行一些长时间运行的作业以响应用户的操作(例如单击),只需使用wait和Task。运行:

这将使用线程池中的后台线程来运行计算并释放UI线程。当计算完成时,执行将在UI线程中恢复,并在等待后执行语句。。。打电话

async/await可用于对数据库、服务器和文件进行异步IO调用。在这种情况下,没有后台处理。在等待服务器或磁盘响应时不会阻塞,而是在异步调用完成时释放UI线程并恢复执行:

public async void myButton_Click(object sender, EventArguments arg)
{
    var client=new HttpClient();
    ....
    var result=await client.GetStringAsync(someUrl);
    txtBox1.Text=result;
}
在许多情况下,您希望将一些数据排队以供最终处理,例如从多个线程或任务写入日志文件。或者,您可能有一个线程,该线程生成另一个线程/任务需要使用的数据,而不阻塞原始线程

在这种情况下,可以使用许多技术和类

也许最困难的是使用TPL数据流库中的ActionBlock类。它允许其他线程异步向其发布消息,它缓冲数据并使用一个或多个任务处理消息。默认情况下,仅使用一个任务:

var logBlock= new ActionBlock<string>(msg=>File.AppendLine("log.txt",msg));
最后,TPL Dataflow中的类提供ReceiveAsync,因此无需阻止等待消息:

var queue = new BufferBlock<string>();

var producer = Task.Run(async ()=>{
        for(i=0;i<100;i++)
        {
            queue.Post($"Message {i}");
            await Task.Delay(100);
        }
        queue.Complete();
    });

var consumer = Task.Run(async ()=> {
    while(!queue.Completion.IsCompleted)
    {
        var msg=await queue.ReceiveAsync();
        File.AppendLine("log.txt",msg);
    }
});

两条线程相互独立。除非数据在数据库中持久化,否则它们不能共享数据。现在,你的问题还不清楚。它是什么应用程序?winform,wpf?你想达到什么目标?到目前为止你试过什么?可以添加一些代码。您查看过lock关键字了吗?这是为了使共享变量线程安全。实际上,将对象传递给线程的概念并不多,您确实希望将工作转移到后台线程,这样UI就不会阻塞。@这是完全错误的,线程可以轻松共享数据。这就是为什么C有lock关键字。如果我想把一个对象从UI传递给一个模块,我想确保UI不必等待任何东西,并且可以立即继续。这就是为什么您应该使用队列。队列阻止UI等待。抱歉,我不清楚我的问题,我仍在编辑。然而,我在队列中遇到的问题是,我使用了锁来防止线程之间的冲突。但可能发生的情况是,如果dequeue持有锁,那么UI必须等待它完成,这不是我想要的。谢谢您的回复,我会尽快完成编辑。这不是SynchronizationContext的工作。你会注意到你指的那篇文章很古老。TPL在那篇文章发表一年后问世。现在我们有了任务、并发集合、数据流、异步/等待ActionBlock,它们已经使用任务提供了这样的功能。将任务与单线程任务计划一起使用也是如此。我没有在服务器软件中使用任务。任务在UI软件中很有用。我在服务器软件中避免它们。为什么不呢?它们是内置的,运行良好,使用的线程池是您的代码所没有的,因此它们不必支付创建线程的成本。它们支持优雅的取消、合并和进度报告,这是原始线程所无法做到的。就这个问题而言,ActionBlock与这段代码没有什么不同——单个任务将处理所有输入。线程池仅在需要无限数量的线程/任务时才有用。就我而言,我正在为机器人编程。我使用了线程池,但阻塞了作业算法的执行,无法控制机器人作业。每个机器人处理一条固定的线。任务可能很好,但不适合确定性工作。还有
threadpool不提供有关执行延迟的详细信息。当需要锁定时,批处理是有用的。我的解决方案基于我的工作,可能不是OP的最佳选择。它可能会给人一些启发。相反,通过设置最小和最大线程限制,线程池可以很好地处理固定数量的线程。很难说,一个接一个地创建100个线程比准备使用100个线程要好。默认最大值约为8000。所有的概念都来自Robotics运行时,数据流使用几乎相同的抽象。不管怎样,您描述的是代理,它们与TasksHanks一起工作没有问题,可以进行详细解释。我认为ConcurrentQueue可以解决我以前认为多线程总是需要锁的问题,但你说得更清楚了很抱歉,昨天我陷入了自己的思维,没有更新我的编辑。
public async void myButton_Click(object sender, EventArguments arg)
{
    var client=new HttpClient();
    ....
    var result=await client.GetStringAsync(someUrl);
    txtBox1.Text=result;
}
var logBlock= new ActionBlock<string>(msg=>File.AppendLine("log.txt",msg));
HttpClient client=new HttpClient();

var options=new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism = 10};
var downloadBlock= new ActionBlock<Tuple<string,string>>(async msg=>{
    var content=await client.GetStringAsync(msg.Item1);
    await File.AppendText(msg.Item2,content));
}

downloadBlock.Post(Tuple.Create(someUrl,someFile));
var queue = new ConcurrentQueue<string>(10);

var producer = Task.Run(async ()=>{
        for(i=0;i<100;i++)
        {
            queue.Enqueue($"Message {i}");
            await Task.Delay(100);
        }
    });

var consumer = Task.Run(()=> {
    while(true)
    {
        if (queue.TryDequeue(var out msg))
        {
            File.AppendLine("log.txt",msg);
        }
    }
});
var queue = new BlockingCollection<string>(10);

var producer = Task.Run(async ()=>{
        for(i=0;i<100;i++)
        {
            queue.Add($"Message {i}");
            await Task.Delay(100);
        }
        queue.CompleteAdding();
    });

var consumer = Task.Run(()=> {
    while(!queue.IsCompleted)
    {
        var msg=queue.Take();
        File.AppendLine("log.txt",msg);
    }
});
var queue = new BufferBlock<string>();

var producer = Task.Run(async ()=>{
        for(i=0;i<100;i++)
        {
            queue.Post($"Message {i}");
            await Task.Delay(100);
        }
        queue.Complete();
    });

var consumer = Task.Run(async ()=> {
    while(!queue.Completion.IsCompleted)
    {
        var msg=await queue.ReceiveAsync();
        File.AppendLine("log.txt",msg);
    }
});