如何在正在运行的线程上调用方法?

2024-01-25

在控制台应用程序上,我当前正在启动一组线程。线程被传递一个对象并在其中运行一个方法。我想知道如何在各个运行线程内的对象上调用方法。

调度员不工作。 SynchronizationContext“Send”在调用线程上运行,“Post”使用新线程。我希望能够调用该方法并在其运行的目标线程上的正在运行的线程上传递参数,而不是调用线程。

更新2:示例代码

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CallingFromAnotherThread
{
    class Program
    {
        static void Main(string[] args)
        {
            var threadCount = 10;
            var threads = new Thread[threadCount];
            Console.WriteLine("Main on Thread " + Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < threadCount; i++)
            {
                Dog d = new Dog();
                threads[i] = new Thread(d.Run);
                threads[i].Start();
            }
            Thread.Sleep(5000);

            //how can i call dog.Bark("woof");
            //on the individual dogs and make sure they run on the thread they were created on.
            //not on the calling thread and not on a new thread.
        }

    }

    class Dog
    {
        public void Run()
        {
            Console.WriteLine("Running on Thread " + Thread.CurrentThread.ManagedThreadId);
        }

        public void Bark(string text)
        {
            Console.WriteLine(text);
            Console.WriteLine("Barking on Thread " + Thread.CurrentThread.ManagedThreadId);
        }
    }
}

更新1: 使用synchronizationContext.Send结果到使用调用线程

Channel created
Main thread  10
SyncData Added for thread 11
Consuming channel ran on thread 11   
Calling AddConsumer on thread 10
Consumer added consumercb78b. Executed on thread 10
Calling AddConsumer on thread 10
Consumer added consumer783c4. Executed on thread 10

使用synchronizationContext.Post结果来使用不同的线程

Channel created
Main thread  10
SyncData Added for thread 11
Consuming channel ran on thread 11   
Calling AddConsumer on thread 12
Consumer added consumercb78b. Executed on thread 6
Calling AddConsumer on thread 10
Consumer added consumer783c4. Executed on thread 7

目标线程must“自身”运行代码 - 或者它只是跨线程访问对象。这是通过目标线程本身上某种形式的事件调度循环来完成的。

SynchronizationContext 抽象can and does支持这个if底层提供商支持它。例如,在 WinForms 或 WPF(它们本身使用“窗口消息泵”)中使用Post将“在 UI 线程上运行”。

基本上,所有此类构造都遵循模式的一些变体:

// On "target thread"
while (running) {
   var action = getNextDelegateFromQueue();
   action();
}

// On other thread
postDelegateToQueue(actionToDoOnTargetThread);

创建一个相当简单原始手动队列系统 - 只需确保使用正确的同步防护即可。 (尽管我确信那里有整洁的“已解决的问题”库;包括将所有内容包装到 SynchronizationContext 中。)


Here is a primitive version of the manual queue. Note that there may be is1 a race condition.. but, FWIW:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DogPark
{
    internal class DogPark
    {

        private readonly string _parkName;
        private readonly Thread _thread;
        private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
        private volatile bool _isOpen;

        public DogPark(string parkName)
        {
            _parkName = parkName;
            _isOpen = true;
            _thread = new Thread(OpenPark);
            _thread.Name = parkName;
            _thread.Start();
        }

        // Runs in "target" thread
        private void OpenPark(object obj)
        {
            while (true)
            {
                Action action;
                if (_actions.TryDequeue(out action))
                {
                    Program.WriteLine("Something is happening at {0}!", _parkName);
                    try
                    {
                        action();
                    }
                    catch (Exception ex)
                    {
                        Program.WriteLine("Bad dog did {0}!", ex.Message);
                    }
                }
                else
                {
                    // Nothing left!
                    if (!_isOpen && _actions.IsEmpty)
                    {
                        return;
                    }
                }

                Thread.Sleep(0); // Don't toaster CPU
            }
        }

        // Called from external thread
        public void DoItInThePark(Action action)
        {
            if (_isOpen)
            {
                _actions.Enqueue(action);
            }
        }

        // Called from external thread
        public void ClosePark()
        {
            _isOpen = false;
            Program.WriteLine("{0} is closing for the day!", _parkName);
            // Block until queue empty.
            while (!_actions.IsEmpty)
            {
                Program.WriteLine("Waiting for the dogs to finish at {0}, {1} actions left!", _parkName, _actions.Count);

                Thread.Sleep(0); // Don't toaster CPU
            }
            Program.WriteLine("{0} is closed!", _parkName);
        }

    }

    internal class Dog
    {

        private readonly string _name;

        public Dog(string name)
        {
            _name = name;
        }

        public void Run()
        {
            Program.WriteLine("{0} is running at {1}!", _name, Thread.CurrentThread.Name);
        }

        public void Bark()
        {
            Program.WriteLine("{0} is barking at {1}!", _name, Thread.CurrentThread.Name);
        }

    }

    internal class Program
    {
        // "Thread Safe WriteLine"
        public static void WriteLine(params string[] arguments)
        {
            lock (Console.Out)
            {
                Console.Out.WriteLine(arguments);
            }
        }

        private static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Home";

            var yorkshire = new DogPark("Yorkshire");
            var thunderpass = new DogPark("Thunder Pass");

            var bill = new Dog("Bill the Terrier");
            var rosemary = new Dog("Rosie");

            bill.Run();

            yorkshire.DoItInThePark(rosemary.Run);
            yorkshire.DoItInThePark(rosemary.Bark);

            thunderpass.DoItInThePark(bill.Bark);

            yorkshire.DoItInThePark(rosemary.Run);

            thunderpass.ClosePark();
            yorkshire.ClosePark();
        }

    }
}

输出应如下所示 - 请记住,这将change由于非同步线程的固有性质而多次运行时。

Bill the Terrier is running at Home!
Something is happening at Thunder Pass!
Something is happening at Yorkshire!
Rosie is running at Yorkshire!
Bill the Terrier is barking at Thunder Pass!
Something is happening at Yorkshire!
Rosie is barking at Yorkshire!
Something is happening at Yorkshire!
Rosie is running at Yorkshire!
Thunder Pass is closing for the day!
Thunder Pass is closed!
Yorkshire is closing for the day!
Yorkshire is closed!

没有什么可以阻止一只狗同时在多个狗公园表演。


1 There is a race condition present and it is this: a park may close before the last dog action runs.

这是因为 Dog Park 线程在操作运行之前将该操作出列 - 并且关闭 Dog Park 的方法只会等到所有操作都出列。

有多种方法可以解决这个问题,例如:

  • 并发队列可以先查看使用,然后在操作后出列,或者
  • 可以使用单独的易失性 isClosed-for-real 标志(从狗公园线程设置),或者..

我已经离开了bug提醒人们穿线的危险。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在正在运行的线程上调用方法? 的相关文章

  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • C# 中的接口继承

    我试图解决我在编写应用程序时遇到的相当大的 对我来说 问题 请看这个 为了简单起见 我将尝试缩短代码 我有一个名为的根接口IRepository
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • 如何使用recv()检测客户端是否仍然连接(并且没有挂起)?

    我写了一个多客户端服务器程序C on SuSE Linux 企业服务器 12 3 x86 64 我为每个客户端使用一个线程来接收数据 我的问题是 我使用一个终端来运行服务器 并使用其他几个终端来运行服务器telnet到我的服务器 作为客户端
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • 如何从 C# 控制器重定向到外部 url

    我使用 C 控制器作为网络服务 在其中我想将用户重定向到外部网址 我该怎么做 Tried System Web HttpContext Current Response Redirect 但没有成功 使用控制器的重定向 http msdn
  • 当前的 c++ 工作草案与当前标准有何不同

    通过搜索该标准的 PDF 版本 我最终找到了这个链接C 标准措辞草案 http www open std org jtc1 sc22 wg21 docs papers 2012 n3376 pdf从 2011 年开始 我意识到我可以购买最终
  • 如何将“外部模板”与由同一类中的模板化成员使用的嵌套类一起使用?

    首先 一些背景信息 我尝试以 Herb Sutter 在他的解决方案中介绍的方式使用 Pimpl 习语 得到了 101 http herbsutter com gotw 101 这在头文件中看起来像这样 include pimpl h h
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • C# 中条件编译符号的编译时检查(参见示例)?

    在 C C 中你可以这样做 define IN USE 1 define NOT IN USE 1 define USING system 1 system 1 IN USE 进而 define MY SYSTEM IN USE if US
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • 获取 2 个数据集 c# 中的差异

    我正在编写一个简短的算法 它必须比较两个数据集 以便可以进一步处理两者之间的差异 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标 我的方法如下所示 private DataSet ComputateDiff DataSet
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • System.Runtime.InteropServices.COMException(0x80040154):[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我在 C 项目中遇到异常 System Runtime InteropServices COMException 0x80040154 检
  • 当前的 x86 架构是否支持非临时加载(来自“正常”内存)?

    我知道有关此主题的多个问题 但是 我没有看到任何明确的答案或任何基准测量 因此 我创建了一个处理两个整数数组的简单程序 第一个数组a非常大 64 MB 第二个数组b很小 无法放入 L1 缓存 程序迭代a并将其元素添加到相应的元素中b在模块化
  • 为什么拆箱枚举会产生奇怪的结果?

    考虑以下 Object box 5 int int int box int 5 int nullableInt box as int nullableInt 5 StringComparison enum StringComparison
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • PHP 检测重复文本

    我有一个网站 用户可以在其中输入有关自己的描述 大多数用户会编写适当的内容 但有些用户只是多次复制 粘贴相同的文本 以创建大量文本的外观 例如 爱一个 和平爱一个 和平爱一个 和平爱一个 和平爱一个 和平爱一个 和平 有没有好的方法可以用
  • vue 2生命周期-如何在Destroy之前停止?

    我可以添加一些东西吗beforeDestroy以防止损坏组件 或者有什么办法可以防止损坏组件 我的情况是 当我通过 vue route 更改 spa 页面时 我首先使用 watch 路由 但我发现这不会触发 因为组件只是销毁了 As 贝尔明
  • 如何在 R 中相对于中心按顺时针顺序对点进行排序?

    我有一个带有 X 和 Y 坐标的数据集 我试图找出一种方法来从中心沿 R 的顺时针 或逆时针 方向对它们进行排序 假设以纬度和经度的中位数为中心 样本数据 df lt structure list name c A B C D E F G
  • 复制省略法

    从复制省略法的标准定义来看 在 C 计算机编程中 复制省略是指消除不必要的对象复制的编译器优化技术 让我们考虑以下代码 include
  • java初学者if/else if问题

    尝试设置 String 变量的代码块似乎出了问题 因为无论我运行程序时做什么 对话框总是显示 otto txt 有谁知道我在这里做错了什么 谢谢 猎食 import java awt FlowLayout import java awt e
  • 如何用 python 显式绘制 y 轴

    I used pp yscale log 在我的 python 脚本中绘制一个以对数刻度显示 y 刻度的图形 然而 图中并没有出现y轴 有没有办法在python中显式显示y轴 leg pp legend series labels loc
  • 适用于 iPhone 的 Flex 应用程序

    是否可以使用 Adob e Flex AIR 为 iPhone 制作应用程序 有教程 指点吗 不 我不相信你能做到 尽管 iPhone 支持 Flash 的传闻已经有一段时间了 但它仍然未能实现 预计到达时间 看来现在这是可能的 http
  • RestSharp 序列化为 JSON,对象未按预期使用 SerializeAs 属性

    我在用休息锐利 通过 NuGet 的版本 104 4 调用 Rest Web 服务 我设计了一组与 API 中公开的资源相匹配的对象 POCO 但是 我的对象属性名称与发布数据时 Rest 服务所期望的名称不匹配 因此当我向 Rest 服务
  • Swagger 永久授权令牌

    我正在 ASP NET Core MVC 中开发 Web api 我想知道是否有一种方法可以使swagger中的授权令牌持久化 这样就不需要每次运行应用程序时都手动进行授权 这将使测试变得更容易 您可以使用persistAuthorizat
  • 如何在 WinDbg 扩展中基于转储文件内存创建对象?

    我负责开发一个大型应用程序 并经常使用 WinDbg 根据客户提供的 DMP 文件来诊断问题 我为 WinDbg 编写了一些小扩展 事实证明它们对于从 DMP 文件中提取信息非常有用 在我的扩展代码中 我发现自己以相同的方式一遍又一遍地手动
  • 强制 iOS 设备改变方向

    首先 我很抱歉再次提出同样的问题 这个问题已经在这个论坛上被问过很多次了 但是 我的问题是我已经尝试了所有建议的解决方案 但仍然没有解决我的问题 我有一个ViewControllerA在肖像模式下和ViewControllerB在横向模式下
  • Google 地图 API v3 - GIcon 未定义

    我知道 v2 到 v3 存在一些问题 我可以在这里做什么来解决它 v3 不支持 GIcon Google Map icon object var gMapIcon new GIcon G DEFAULT ICON change to new
  • 使用 data.table 包进行条件二进制连接和引用更新

    这是我现实生活中的问题 我觉得可以很容易地解决 但我在这里遗漏了一些明显的东西 我有两个大数据集TK and DFT library data table set seed 123 TK lt data table venue id rep
  • 远程调试符号文件格式

    有谁知道远程调试符号文件的文件格式 项目 gt 选项 gt 链接 gt 包括远程调试符号 None
  • 在Python中声明编码[重复]

    这个问题在这里已经有答案了 我想使用以下代码在 python 中分割字符串 means a b c lst means split 但我收到此错误消息 SyntaxError 文件 dict py 第 2 行中存在非 ASCII 字符 xd
  • 使用 Autofac 解析 MVC5 应用程序中的 IOwinContext

    我使用时遇到问题MembershipReboot使用新的 ASP MVC5 模板和Autofac 我使用默认的 MVC5 模板来设置站点 然后尝试连接MembershipReboot框架作为模板附带的 ASP Identity 框架的替代品
  • 如何使用 JavaScript 将引导图标添加到画布上?如果有办法的话

    这是我到目前为止所尝试过的 ctx setAttribute class glyphicon glyphicon time 但是也 var icon document createElement span icon className gl
  • 有什么方法可以将自定义元素的模板标记和样式保留在 JavaScript 字符串之外?

    这是使用自定义元素的示例开发者 google com https developers google com web fundamentals web components customelements let tmpl document
  • R:在一页上打印多种类型的绘图

    我正在尝试在一页上绘制多个图 我知道像这样的函数gridExtra grid arrange可以绘制由以下生成的图表ggplot2包裹 我面临的问题是我有两个地块 bar plot and density plot如下 是由生成的ggplo
  • 如何在正在运行的线程上调用方法?

    在控制台应用程序上 我当前正在启动一组线程 线程被传递一个对象并在其中运行一个方法 我想知道如何在各个运行线程内的对象上调用方法 调度员不工作 SynchronizationContext Send 在调用线程上运行 Post 使用新线程