最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#使用channel實現(xiàn)Plc異步任務之間的通信

 更新時間:2024年05月15日 10:57:14   作者:潘諾西亞的火山  
在C#的并發(fā)編程中,Channel是一種非常強大的數(shù)據(jù)結(jié)構(gòu),用于在生產(chǎn)者和消費者之間進行通信,本文將給大家介紹C#使用channel實現(xiàn)Plc異步任務之間的通信,文中有相關的代碼示例供大家參考,感興趣的朋友跟著小編一起來看看吧

channel 通信的例子:

using ConsoleApp2;
using System.Collections.Concurrent;
using System.Threading.Channels;

var queue = new BlockingCollection<Message>(new ConcurrentQueue<Message>());

var opt = new BoundedChannelOptions(10)
{
    FullMode = BoundedChannelFullMode.Wait,
    SingleReader = true,
    SingleWriter = true,
    Capacity = 100 //最大容量
};

//有限的
var channelTest = Channel.CreateBounded<Message>(opt);


//無限的
var channel = Channel.CreateUnbounded<Message>();

var sender1 = SendMessageThreadAsync(channel.Writer, 1);
var sender2 = SendMessageThreadAsync(channel.Writer, 2);
var receiver1 = ReceiveMessageThreadAsync(channel.Reader, 3);
var receiver2 = ReceiveMessageThreadAsync(channel.Reader, 4);
//await sender;
// make sure all messages are received

await Task.WhenAll(sender1, sender2);

channel.Writer.Complete();

await Task.WhenAll(receiver1, receiver2);

//await receiver;

Console.WriteLine("Press any key to exit...");
Console.ReadKey();

async Task SendMessageThreadAsync(ChannelWriter<Message> writer, int id)
{
    for (int i = 0; i < 20; i++)
    {
        await writer.WriteAsync(new Message(id, i.ToString()));
        Console.WriteLine($"Thread {id} sent {i}");
        await Task.Delay(100);
    }
}

async Task ReceiveMessageThreadAsync(ChannelReader<Message> reader, int id)
{

    //try
    //{
    //    while (!reader.Completion.IsCompleted)
    //    {
    //        var message = await reader.ReadAsync();
    //        Console.WriteLine($"Thread {id} received {message.Content}");
    //    }
    //}
    //catch (Exception ex)
    //{
    //    Console.WriteLine($"Thread {id} channel closed:{ex.Message}");
    //}

    await foreach (var message in reader.ReadAllAsync())
    {
        Console.WriteLine($"Thread {id} received {message.Content}");
    }
}

record Message(int FromId, string Content);






改造為Plc的實例

record PlcDataMessage  
{  
    public bool IsConnected { get; init; }  
    public DbData DbData { get; init; }  
    // 可以添加其他需要傳遞的信息  
}
// 創(chuàng)建一個無邊界的Channel來發(fā)送和接收消息  
var plcDataChannel = Channel.CreateUnbounded<PlcDataMessage>();  
  
// 啟動一個新的任務來模擬PLC數(shù)據(jù)讀取  
Task.Factory.StartNew(async () =>  
{  
    var cts = new CancellationTokenSource(); // 假設您已經(jīng)有了取消令牌源  
    while (!cts.IsCancellationRequested)  
    {  
        try  
        {  
            // ... 省略了連接PLC的代碼,這部分邏輯保持不變 ...  
  
            if (MyIsConnected)  
            {  
                DbData dbDataTemp = await s7Plc.ReadClassAsync<DbData>(42, 0);  
  
                // 心跳和其他操作...  
  
                // 構(gòu)造消息并發(fā)送到Channel  
                var message = new PlcDataMessage  
                {  
                    IsConnected = MyIsConnected,  
                    DbData = dbDataTemp  
                };  
                await plcDataChannel.Writer.WriteAsync(message, cts.Token);  
            }  
  
            // ... 其他邏輯保持不變 ...  
        }  
        catch (Exception ex)  
        {  
            // 處理異常并重新連接PLC(如果需要)  
            // ...  
  
            // 可以通過Channel發(fā)送一個特殊的消息來表示連接已斷開或發(fā)生了錯誤  
            // 這里省略了這部分邏輯  
  
            // 休眠一段時間后再重試  
            await Task.Delay(2000, cts.Token);  
        }  
    }  
  
    // 完成后通知Channel不再發(fā)送更多數(shù)據(jù)  
    plcDataChannel.Writer.Complete();  
}, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);  
  
// 在另一個任務或線程中讀取Channel中的數(shù)據(jù)  
Task.Run(async () =>  
{  
    await foreach (var message in plcDataChannel.Reader.ReadAllAsync(cts.Token))  
    {  
        if (message.IsConnected)  
        {  
            lock (lockObj)  
            {  
                // 更新dbData,這里假設dbData是一個線程安全的對象或結(jié)構(gòu)  
                dbData.Str_S = message.DbData.Str_S.Trim();  
                // ... 更新其他屬性 ...  
            }  
            // 處理讀取到的數(shù)據(jù)...  
        }  
        else  
        {  
            // 處理PLC斷開連接的情況...  
        }  
    }  
  
    // 讀取完成,Channel已關閉  
    Console.WriteLine("PLC數(shù)據(jù)讀取完畢。");  
}, cts.Token);  
  
// ... 其他代碼,如等待所有任務完成、處理取消邏輯等 ...
using System;  
using System.Threading;  
using System.Threading.Channels;  
using System.Threading.Tasks;  
  
// ... 其他必要的引用和類型定義 ...  
  
// 創(chuàng)建一個無邊界的Channel來發(fā)送和接收消息  
var plcDataChannel = Channel.CreateUnbounded<PlcDataMessage>();  
  
// 取消令牌源  
var cts = new CancellationTokenSource();  
  
// 啟動一個新的任務來模擬PLC數(shù)據(jù)讀取  
Task.Run(async () =>  
{  
    Plc s7Plc = null;  
    bool MyIsConnected = false;  
    int errorTimes = 0;  
  
    try  
    {  
        while (!cts.IsCancellationRequested)  
        {  
            if (s7Plc == null || !MyIsConnected)  
            {  
                // 嘗試連接PLC(略去具體實現(xiàn))  
                // ...  
  
                if (MyIsConnected)  
                {  
                    // 連接成功,發(fā)送連接成功消息(如果需要)  
                    // ...  
                }  
            }  
            else  
            {  
                try  
                {  
                    // 讀取PLC數(shù)據(jù)(略去具體實現(xiàn))  
                    DbData dbDataTemp = await s7Plc.ReadClassAsync<DbData>(42, 0, cts.Token);  
  
                    // 心跳和其他操作...  
  
                    // 構(gòu)造消息并發(fā)送到Channel  
                    var message = new PlcDataMessage { IsConnected = MyIsConnected, DbData = dbDataTemp };  
                    await plcDataChannel.Writer.WriteAsync(message, cts.Token);  
  
                    errorTimes = 0; // 重置錯誤計數(shù)器  
                }  
                catch (Exception ex)  
                {  
                    errorTimes++;  
                    // 處理異常(例如記錄日志)  
                    // ...  
  
                    // 在達到一定錯誤次數(shù)后,關閉PLC連接并重置  
                    if (errorTimes > someThreshold)  
                    {  
                        s7Plc?.Close();  
                        s7Plc = null;  
                        MyIsConnected = false;  
                        // 可以選擇發(fā)送一個斷開連接的消息到Channel  
                    }  
  
                    // 休眠一段時間后再重試  
                    await Task.Delay(2000, cts.Token);  
                }  
            }  
  
            // 可以添加一些延時來減少循環(huán)的頻率  
            await Task.Delay(somePollingInterval, cts.Token);  
        }  
    }  
    catch (OperationCanceledException)  
    {  
        // 取消是預期的,不需要額外處理  
    }  
    finally  
    {  
        // 確保關閉PLC連接和Channel寫入器  
        s7Plc?.Close();  
        plcDataChannel.Writer.Complete();  
    }  
}, cts.Token);  
  
// 在另一個任務或線程中讀取Channel中的數(shù)據(jù)  
Task.Run(async () =>  
{  
    await foreach (var message in plcDataChannel.Reader.ReadAllAsync(cts.Token))  
    {  
        if (message.IsConnected)  
        {  
            // 更新dbData(這里假設dbData是一個線程安全的對象或結(jié)構(gòu))  
            // 根據(jù)需要添加適當?shù)耐綑C制  
            // ...  
  
            // 處理讀取到的數(shù)據(jù)...  
        }  
        else  
        {  
            // 處理PLC斷開連接的情況...  
        }  
    }  
  
    // 讀取完成,Channel已關閉  
    Console.WriteLine("PLC數(shù)據(jù)讀取完畢。");  
}, cts.Token);  
  
// ... 其他代碼,如等待所有任務完成、處理取消邏輯等 ...  
  
// 在某個適當?shù)臅r刻取消任務  
// cts.Cancel();  
  
// 等待所有任務完成(如果需要

拓展:C# Channel實現(xiàn)線程間通信

C# Channel實現(xiàn)線程間通信

同步方式實現(xiàn):

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

namespace ConsoleApp1
{
    public class ChannelDemo
    {
        static Channel<Message> channel1 = Channel.CreateUnbounded<Message>();
        public static void Main2()
        {
            sender.Start(1);
            receive1.Start(2);
            receive2.Start(3);
            sender.Join();
            Thread.Sleep(3000);
            receive1.Interrupt();
            receive2.Interrupt();

            receive1.Join();
            receive2.Join();


            Console.ReadKey();
        }
        static Thread sender = new Thread(SendMsg);

        static Thread receive1 = new Thread(ReceiveMsg);
        static Thread receive2 = new Thread(ReceiveMsg);

        static void SendMsg(object id)
        {
            for (int i = 0; i < 20; i++)
            {
                if (channel1.Writer.TryWrite(new Message((int)id, i.ToString())))
                {
                    Console.WriteLine($"【線程{id}】發(fā)送了【{i}】");
                }
            }
        }

        static void ReceiveMsg(object id)
        {
            try
            {
                while (true)
                {
                    if (channel1.Reader.TryRead(out Message message))
                    {
                        Console.WriteLine($"【線程{id}】從【線程{message.id}】接收了【{message.content}】");

                    }
                    Thread.Sleep(1);
                }
            }
            catch (ThreadInterruptedException ex)
            {
                Console.WriteLine($"接收結(jié)束");
            }
        }
    }
}


異步方式:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class ChannelDemo2
    {
        static Channel<Message> channel1 = Channel.CreateUnbounded<Message>();
        
         public static async void Main2()
        {
            await Task.WhenAll(sender, sender2);
            channel1.Writer.Complete();
            await Task.WhenAll(receive1, receive2);
           
            Console.ReadKey();
        }

        static Task sender = SendMsgAsync(channel1.Writer, 1);
        static Task sender2 = SendMsgAsync(channel1.Writer, 4);
        static Task receive1 = ReceiveMsgAsync(channel1.Reader, 2);
        static Task receive2 = ReceiveMsgAsync(channel1.Reader, 3);

        static async  Task SendMsgAsync(ChannelWriter<Message> writer, int id)
        {
            for (int i = 0; i < 20; i++)
            {
                await writer.WriteAsync(new Message((int)id, i.ToString()));
                Console.WriteLine($"【線程{id}】發(fā)送了【{i}】");
            }
        }

        static async Task ReceiveMsgAsync(ChannelReader<Message> reader,int id)
        {
            try
            {
                while (!reader.Completion.IsCompleted)
                {
                    Message message = await reader.ReadAsync();           
                    Console.WriteLine($"【線程{id}】從【線程{message.id}】接收了【{message.content}】");
                   
                }
            }
            catch (ChannelClosedException ex)
            {
                Console.WriteLine($"ChannelClosed 接收結(jié)束");
            }
        }

    }
}


在對Channel進行實例化的時候,也可以傳遞一個Options,這里面可以對消息容量,是否多個發(fā)送者和接受者進行定義。

以上就是C#使用channel實現(xiàn)Plc異步任務之間的通信的詳細內(nèi)容,更多關于C# channel Plc異步通信的資料請關注腳本之家其它相關文章!

相關文章

  • Unity實現(xiàn)簡易日志輸出功能

    Unity實現(xiàn)簡易日志輸出功能

    這篇文章主要為大家詳細介紹了Unity實現(xiàn)簡易日志輸出功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • c# 使用OpenCV識別硬幣

    c# 使用OpenCV識別硬幣

    這篇文章主要介紹了c# 使用OpenCV識別硬幣的方法,幫助大家更好的利用c#進行深度學習,感興趣的朋友可以了解下
    2020-12-12
  • C# wpf Brush轉(zhuǎn)Hex字符串的實例代碼

    C# wpf Brush轉(zhuǎn)Hex字符串的實例代碼

    這篇文章主要介紹了C# wpf Brush轉(zhuǎn)Hex字符串的實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • C#使用Spire.XLS for .NET將DataTable寫入Excel的具體步驟

    C#使用Spire.XLS for .NET將DataTable寫入Excel的具體步驟

    在日常開發(fā)中,我們經(jīng)常需要將 DataTable 中的數(shù)據(jù)導出到 Excel 文件中,方便用戶查看或進行后續(xù)分析,本文將介紹如何使用 Spire.XLS for .NET 實現(xiàn)這一功能,需要的朋友可以參考下
    2025-08-08
  • WPF實現(xiàn)窗體中的懸浮按鈕

    WPF實現(xiàn)窗體中的懸浮按鈕

    這篇文章主要為大家詳細介紹了WPF實現(xiàn)窗體中的懸浮按鈕,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • C#二維數(shù)組與多維數(shù)組的具體使用

    C#二維數(shù)組與多維數(shù)組的具體使用

    本文主要介紹了C#二維數(shù)組與多維數(shù)組的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • c#入門之循環(huán)語句使用詳解(for循環(huán)、do/while)

    c#入門之循環(huán)語句使用詳解(for循環(huán)、do/while)

    這篇文章主要介紹了c#入門之循環(huán)語句使用詳解,有for循環(huán)和do/while的示例,需要的朋友可以參考下
    2014-04-04
  • C#本地項目引用失效與恢復的全指南

    C#本地項目引用失效與恢復的全指南

    本文詳細介紹了如何解決Visual Studio中項目引用失效的問題,包括錯誤原因分析、解決步驟、進階知識以及推薦的解決方案結(jié)構(gòu),通過這些步驟,讀者可以有效解決CS0006未能找到元數(shù)據(jù)文件的問題,并掌握Visual Studio項目間依賴管理的核心機制,需要的朋友可以參考下
    2025-11-11
  • c# 并行和多線程編程——認識Parallel

    c# 并行和多線程編程——認識Parallel

    這篇文章主要介紹了c# 并行和多線程編程的相關資料,幫助大家更好的理解和學習c# Parallel的相關知識,感興趣的朋友可以了解下
    2021-02-02
  • C#數(shù)組去重的方法匯總

    C#數(shù)組去重的方法匯總

    本文總結(jié)了C#中數(shù)組和List類型去重的多種方法,包括使用LINQ的Distinct()方法、HashSet、GroupBy方法等,文章還比較了不同方法的性能,并推薦了針對不同場景的最佳方法,需要的朋友可以參考下
    2026-01-01

最新評論

松溪县| 德清县| 宿迁市| 外汇| 永宁县| 北京市| 景泰县| 仪征市| 虎林市| 铜川市| 富源县| 徐州市| 明星| 长兴县| 庆安县| 澄城县| 阿拉善左旗| 仙桃市| 离岛区| 黎川县| 南丹县| 综艺| 皮山县| 合肥市| 广水市| 余姚市| 许昌县| 腾冲县| 和林格尔县| 南召县| 鹤山市| 那坡县| 汕尾市| 二连浩特市| 拉萨市| 阿拉善左旗| 平凉市| 乌鲁木齐市| 通河县| 都兰县| 龙陵县|