Hello, many thanks to everyone who answers!

So I myself got to the point where I can not figure it out, I ask for your help. There is such a code: in a nutshell, the application connects to the exchange program, which by means of the RTD interface in real time gives data about quotes and their updating, the problem is just in the update.

Outside, my UpdateNotify() function is UpdateNotify() class.

  1. How to build the logic of transferring control inside the application, provided one of the functions is called from the outside?
  2. Where should the code be transferred to the new thread under the same condition (calling one of the functions from the outside)?
  3. What should be considered when writing functions that are called from the outside?

There is such code:

  <code> public partial class Form1 : Form { //создаСм ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚ΠΈΠΏΠ° RtdClient RtdClient rtdClient; //создаСм ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚ΠΈΠΏΠ° updateNotification RtdUpdate rtdUpdate; //конструктор Form1 public Form1() { InitializeComponent(); var tosClassId = new Guid(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\myapp.COMApp.1\CLSID\", "", null).ToString()); rtdClient = new RtdClient(tosClassId, this); //отправляСм ссылку Π½Π° наш ΠΊΠ»ΠΈΠ΅Π½Ρ‚, для ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ rtdUpdate = new RtdUpdate(ref rtdClient); //подписываСм наш ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° обновлСния rtdClient.StartListenUpdate(ref rtdUpdate); } //функция, обновляСт значСния Π² массивах, Ссли ΠΏΡ€ΠΈΡˆΠ»ΠΎ update public void UpdateOnePrice(object _inputSendDataToThread) { /* Ρ‚ΡƒΡ‚ ΠΊΠΎΠ΄ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ */ } //класс Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ RtdClient public class RtdClient { Form1 form; Type rtd; IRtdServer server; public RtdClient(Guid _serverId, Form1 _form) { form = _form; rtd = Type.GetTypeFromCLSID(_serverId); server = (IRtdServer)Activator.CreateInstance(rtd); } public void StartListenUpdate(ref RtdUpdate _rtdUpdate) { server.ServerStart(_rtdUpdate); } public void updateData() { try { var refresh = server.RefreshData(1); if (refresh.Length > 0) { sendDataToThread send = new sendDataToThread(); send.data[0, 0] = refresh[0, 0]; send.data[1, 0] = refresh[1, 0]; form.UpdateOnePrice(send); } } catch (Exception ex) { // TODO: Log exception MessageBox.Show("error:" + ex); } } } public class RtdUpdate : IRTDUpdateEvent { RtdClient rtdClient = null; ThreadManager threadManager; public delegate void MethodContainer(); public RtdUpdate(ref RtdClient _rtdClient) { rtdClient = _rtdClient; threadManager = new ThreadManager(); } public void UpdateNotify() { //ΡƒΠ·Π½Π°Π΅ΠΌ Π½ΠΎΠΌΠ΅Ρ€ свободного ΠΏΠΎΡ‚ΠΎΠΊΠ° int numThread = -1; while (numThread < 0) { numThread = threadManager.FreeThreadPlz(); } //запускаСм ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Π² свободном ΠΏΠΎΡ‚ΠΎΠΊΠ΅ threadManager.threads[numThread] = new Thread(new ThreadStart(rtdClient.updateData)); threadManager.threads[numThread].Start(); } } //класс для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ, Ρ‚ΠΎ Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ Π² Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ public class sendDataToThread { public object[,] data = new object[2, 1]; } //класс ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ public class ThreadManager { //ΠΊΠΎΠ»-Π²ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² int threadCount = 10; //массив с Ρ€Π°Π±ΠΎΡ‡ΠΈΠΌΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ public Thread[] threads = new Thread[10]; //ΠΊΠ°ΠΊΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ сСйчас свободСн public int FreeThread = 0; //конструктор public ThreadManager() { Array.Resize(ref threads, threadCount); } public int FreeThreadPlz() { int i = 0; for (i = 0; i < threadCount; i++) { try { if (!threads[i].IsAlive) { return i; } } catch (Exception) { return i; } } /* LOG TO all BUSY THREAD */ return -1; } } //Π½ΠΈΠΆΠ΅ описаниС интСрфСйсов [ComImport, TypeLibType((short)0x1040), Guid("EC0E6191-DB51-11D3-8F3E-00C04F3651B8")] public interface IRtdServer { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10)] int ServerStart([In, MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent callback); [return: MarshalAs(UnmanagedType.Struct)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] object ConnectData([In] int topicId, [In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref object[] parameters, [In, Out] ref bool newValue); [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] object[,] RefreshData([In, Out] ref int topicCount); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(13)] void DisconnectData([In] int topicId); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(14)] int Heartbeat(); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(15)] void ServerTerminate(); } //[ComImport, TypeLibType((short)0x1040), Guid("A43788C1-D91B-11D3-8F39-00C04F3651B8")] public interface IRTDUpdateEvent { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10), PreserveSig] void UpdateNotify(); /* [DispId(11)] int HeartbeatInterval { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] get; [param: In] [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] set; } */ [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] void Disconnect(); } } 

  • 7
    Okay. You will have to tell us exactly what this β€œexception is, some kind of COM object, blah, blah, blah”. Because this message is trying to convey to you (well, to us too), what is wrong. - VladD 9:39 pm
  • In order for the exchange program to UpdateNotify() your UpdateNotify() function, it must first create an instance of the RtdUpdate class, passing an instance of RtdClient . Try to make the RtdUpdate class static or singleton. - iRumba
  • The @iRumba exchange does not need to create anything - an instance of the RtdUpdate class RtdUpdate passed as a parameter to the ServerStart method in the constructor. - Pavel Mayorov
  • If an instance of the RtdUpdate class is passed, then the RtdClient in its composition must also be passed. - iRumba
  • @iRumba and what follows from this? - Pavel Mayorov

1 answer 1

I would use the Publish / Subscribe architecture for communication between threads and Inversion of Control to manage the life cycle of threads.

Publish / Subscribe is a kind of data bus within the application through which the threads communicate with each other.

In an IoC container in a separate thread, we create an object that works with a COM object. The object through the delegate receives a message, on its base creates its own internal message that sends to the data bus.

Other threads (interface (viewmodel) or other handlers) are pre-subscribed to messages on this data bus, receive messages and use at their discretion.

Not difficult to mastering Publish / Subscribe and Ioc. Nuget: Microsoft.Practices.Prism.PubSubEvents
IoC container NuGet: Unity 4.0.1

  • Yes, and here Publish / Subscribe? The author has a different problem. You look closely as he requests a free flow ... - Pavel Mayorov
  • Perhaps oftop, I do not solve a specific problem, but I suggest the author to study these 2 techniques and rewrite the code, what do you dislike about this approach? - Marat Batalandabad
  • The author has already picked up ideas that he could not understand - and therefore his program now freezes. And you offer him another incomprehensible idea. Do you really think that if he rewrites the code using pubsub, he will throw out his ThreadManager? No, he will not, and he will have two problems instead of one. - Pavel Mayorov
  • Perhaps the author will not be able to possibly be able to, but at least I tried to propose an approach if, until now, this question is marked β€œno answer”. - Marat Batalandabad