I am making online multiplayer game with Darkrift2 and with Unity.
I deeply know how to make games but i am new at online part.
I made the game succesfully with LAN.
I done the server side.
But just the game that opened with server can connect.
I am putting the server to my pc and go and open the game in another pc.
It can't connect.
I could definitely make an obvious mistake but IPV4 ADDRESS IS SAME AS PC'S IPV4 ADDRESS AND PORT NO IS SAME ON EVERY PC.
Also there is no firewall ban, Game is opening in another pc's.
By the way probably you don't have to read the whole code, Just the connection part.
Client
NetworkManager.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DarkRift.Client.Unity;
using DarkRift;
using Tags;
using DarkRift.Client;
using UnityEngine.InputSystem;
using System.Net;
using System.Linq;
public class NetworkManager : MonoBehaviour
{
IPAddress IPv4;
public UnityClient client;
public GameObject Bug;
public Transform[] PlayerBegin;
public Light DirLight;
public List<GameObject> Bugs;
private void Awake()
{
IPv4 = Dns.GetHostEntry(Dns.GetHostName())
.AddressList.First(
f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
Debug.Log(IPv4);
client.Connect(IPv4, client.Port, true);
client.MessageReceived += OnMessageReceived;
//DontDestroyOnLoad(gameObject);
}
private void OnDestroy()
{
client.MessageReceived -= OnMessageReceived;
}
public void Interaction(byte Condition)//legdeathi de içine koyunca sorun yaratır mı? sanırım hayır
{
using (DarkRiftWriter writer = DarkRiftWriter.Create())
{
writer.Write(client.ID);
writer.Write(Condition);
using (Message message = Message.Create((ushort)Models.Tags0.InteractionType, writer))
{
client.SendMessage(message, SendMode.Reliable);
}
}
}
public void PosRot(Vector3 Pos, Quaternion Rot, bool ThereIsPos)
{
XYZ Position=null;
if (ThereIsPos)
{
Position = new XYZ();
Position.X = Pos.x;
Position.Y = Pos.y;
Position.Z = Pos.z;
}
XYZ Rotation = new XYZ();
Rotation.X = Rot.x;
Rotation.Y = Rot.y;
Rotation.Z = Rot.z;
float RotW = Rot.w;
using (DarkRiftWriter writer = DarkRiftWriter.Create())
{
writer.Write(client.ID);
var tag = Models.Tags0.Rot;
if (ThereIsPos)
{
tag = Models.Tags0.PosRot;
writer.Write(Position);
}
writer.Write(Rotation);
writer.Write(RotW);
using (Message message = Message.Create((ushort)tag, writer))
{
client.SendMessage(message, SendMode.Unreliable);
}
}
}
public int PlayerId;
public ushort PlayerCount;
private void OnMessageReceived(object sender, MessageReceivedEventArgs e)
{
using (Message message = e.GetMessage())
{
using (DarkRiftReader reader = message.GetReader())
{
if (message.Tag == (ushort)Models.Tags0.InteractionType)
{
ushort Id = reader.ReadUInt16();
GameObject tarantula = Bugs[Id].transform.GetChild(0).gameObject;
byte Interaction = reader.ReadByte();
Spider s = tarantula.GetComponent<Spider>();
switch (Interaction)
{
case 0: s.Attack(); break;
case 1:
s.DefenceGetBug();
break;
case 2:
s.DefenceOff();
break;
case 3:
s.Death();
break;
case 4:
s.LegsHealthDown();
break;
default:
s.LegHealthDown(s.Legs[Interaction - 5], 3);
break;
}
}
byte ThereIsPos=0;
if(message.Tag == (ushort)Models.Tags0.PosRot)
{
ThereIsPos = 1;
}
else if(message.Tag == (ushort)Models.Tags0.Rot)
{
ThereIsPos = 2;
}
if (ThereIsPos != 0)
{
ushort Id = reader.ReadUInt16();
GameObject tarantula = Bugs[Id].transform.GetChild(0).gameObject;
if (ThereIsPos == 1)
{
XYZ Position = reader.ReadSerializable<XYZ>();
tarantula.transform.position = new Vector3(Position.X, Position.Y, Position.Z);
}
XYZ Rotation = reader.ReadSerializable<XYZ>();
float RotW = reader.ReadSingle();
tarantula.transform.rotation = new Quaternion(Rotation.X, Rotation.Y, Rotation.Z, RotW);
}
if (message.Tag == (ushort)Models.Tags0.NewPlayer)
{
PlayerCount = (ushort)(reader.ReadUInt16() + 1);
//Debug.Log("PlayerCount : " + PlayerCount);
PlayerId = Bugs.Count;//Player No
//Debug.Log("PlayerId : " + PlayerId);
while (PlayerId < PlayerCount)
{
Debug.Log("Player Spawn" + PlayerId);
GameObject bug = Instantiate(Bug, PlayerBegin[PlayerId].position, Quaternion.identity, null);
bug.name = "Bug" + PlayerId;
Spider spider;
spider = bug.GetComponentInChildren<Spider>();
spider.nm = this;
spider.DirLight = DirLight;
//spider.transform.position = PlayerBegin[PlayerId].position;
//PosChange(spider.gameObject.transform.position);
if (client.ID != PlayerId)
{
//spider.enabled = false;
bug.transform.Find("Camera").gameObject.SetActive(false);
bug.transform.Find("CM FreeLook1").gameObject.SetActive(false);
bug.transform.Find("Camera Late").gameObject.SetActive(false);
bug.transform.Find("Canvas").gameObject.SetActive(false);
bug.GetComponentInChildren<PlayerInput>().enabled = false;
}
Bugs.Add(bug);
PlayerId++;
}
}
}
}
}
}
Server code .Net (only the main class):
using System;
using DarkRift.Server;
using DarkRift;
using Tags;
namespace Bug_Wars_Online
{
public class BugWarsOnline : Plugin
{
public override bool ThreadSafe => false;
public override Version Version => new Version(1, 0, 0);
public BugWarsOnline(PluginLoadData pluginLoadData) : base(pluginLoadData)
{
ClientManager.ClientConnected += OnClientConnected;
ClientManager.ClientDisconnected += OnClientDisconnected;
}
private void OnClientConnected(object sender, ClientConnectedEventArgs e)
{
Console.WriteLine("Connected");
e.Client.MessageReceived += OnMessageReceived;
using (DarkRiftWriter writer = DarkRiftWriter.Create())
{
writer.Write(e.Client.ID);
writer.Write(0);
using (Message message = Message.Create((ushort)Models.Tags0.NewPlayer, writer))
{
foreach (IClient client in ClientManager.GetAllClients())
{
//if (client.ID != e.Client.ID)
{
client.SendMessage(message, SendMode.Reliable);
Console.WriteLine("Player" + client.ID + " Connected");
Console.WriteLine("ClientManager.Count" + ClientManager.Count);
}
}
}
}
}
private void OnClientDisconnected(object sender, ClientDisconnectedEventArgs e)
{
Console.WriteLine("Disconnected");
//destroy et!
}
private void OnMessageReceived(object sender, MessageReceivedEventArgs e)
{
using (Message message = e.GetMessage())
{
if (message.Tag == (ushort)Models.Tags0.PosRot|| message.Tag == (ushort)Models.Tags0.Rot)
{
foreach (IClient client in ClientManager.GetAllClients())
{
if (client.ID != e.Client.ID)
{
client.SendMessage(message, SendMode.Unreliable);
}
}
}
if (message.Tag == (ushort)Models.Tags0.InteractionType)
{
foreach (IClient client in ClientManager.GetAllClients())
{
if (client.ID != e.Client.ID)
{
client.SendMessage(message, SendMode.Reliable);
}
}
}
}
}
}
}
Okay I should have enter the ipv4 address of server’s pc.
I am using admob ads in my app and they are working fine. But when i try to do something after a ad close or reward earned call back my code breaks. Following is my adMob script
public class AdMobScript : MonoBehaviour
{
...
public event Action OnReviveRewardEarned;
public event Action OnReviveAdLoaded;
public event Action OnReviveAdClosed;
private void LoadReviveRewardedAd()
{
reviveRewardedAd = new RewardedAd(adReviveRewardedId);
reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
reviveRewardedAd.OnAdClosed += ReviveAdClosed;
AdRequest request = new AdRequest.Builder().Build();
reviveRewardedAd.LoadAd(request);
}
private void ReviveAdClosed(object sender, EventArgs e)
{
LoadReviveRewardedAd();
if (isRewardErned)
{
isRewardErned = false;
OnReviveRewardEarned.Invoke();
}
else
OnReviveAdClosed.Invoke();
}
private void ReviveEarnedReward(object sender, Reward e)
{
isRewardErned = true;
}
private void ReviveAdLoaded(object sender, EventArgs e)
{
//reviveButton.interactable = true;
OnReviveAdLoaded.Invoke();
}
public void ShowAdToRevive()
{
if (reviveRewardedAd.IsLoaded())
{
reviveRewardedAd.Show();
}
}
...
}
In the callbacks i am calling my adManager script which is in term using adMob script. Here is the code for it.
public class AdManager : MonoBehaviour
{
...
private void Start() {
AdMobScript.instance.OnReviveAdClosed += ReviveAdClosed;
AdMobScript.instance.OnReviveAdLoaded += ReviveAdLoaded;
AdMobScript.instance.OnReviveRewardEarned += ReviveReward;
}
#region ReviveAds
private void ReviveReward() {
//game crash here
backButton.gameObject.SetActive(true);
reviveButton.gameObject.SetActive(false);
noThanksButton.gameObject.SetActive(false);
manager.Revive();
}
private void ReviveAdLoaded() {
reviveButton.interactable = true;
}
private void ReviveAdClosed() {
//game crash here
reviveButton.interactable = false;
}
public void ShowAdToRevive() {
AdMobScript.instance.ShowAdToRevive();
}
...
}
After either ad close or reward earned my game crashes (error log says
get_gameObject can only be called from the main thread
). There must be something i am doing wrong. Can anyone please point me to the right direction?
The reason for the problem - you trying to manipulate with MonoBehaviors, not in main thread.
Just write simple scheduler which calls the events in the Unity thread, like this:
Scheduler:
using System;
using UnityEngine;
public class Scheduler : MonoBehaviour
{
public static Scheduler instance;
public event Action secondTick = delegate { };
private float seconds = 0;
private void Awake()
{
instance = this;
}
private void Update()
{
seconds += Time.unscaledDeltaTime;
if (seconds >= 1.0f)
{
seconds -= 1.0f;
secondTick.Invoke();
}
}
}
Updated AdMobScript:
public class AdMobScript : MonoBehaviour
{
...
private bool onRewardEarnedCall = false;
private bool onRewardAdLoaded = false;
private bool onRewardAdClosed = false;
public event Action OnReviveRewardEarned;
public event Action OnReviveAdLoaded;
public event Action OnReviveAdClosed;
private void LoadReviveRewardedAd()
{
reviveRewardedAd = new RewardedAd(adReviveRewardedId);
reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
reviveRewardedAd.OnAdClosed += ReviveAdClosed;
AdRequest request = new AdRequest.Builder().Build();
reviveRewardedAd.LoadAd(request);
Scheduler.instance.secondTick += OnSecondTick;
}
private void OnSecondTick()
{
if(onRewardAdClosed)
{
onRewardAdClosed = false;
OnReviveAdClosed.Invoke();
}
if(onRewardEarnedCall)
{
OnReviveRewardEarned.Invoke();
onRewardEarnedCall = false;
}
if(onRewardAdLoaded)
{
OnReviveAdLoaded.Invoke();
onRewardAdLoaded = false;
}
}
private void ReviveAdClosed(object sender, EventArgs e)
{
LoadReviveRewardedAd();
if (isRewardErned)
{
isRewardErned = false;
onRewardEarnedCall = true;
}
else
onRewardAdClosed = true;
}
private void ReviveEarnedReward(object sender, Reward e)
{
isRewardErned = true;
}
private void ReviveAdLoaded(object sender, EventArgs e)
{
//reviveButton.interactable = true;
onRewardAdLoaded = true;
}
public void ShowAdToRevive()
{
if (reviveRewardedAd.IsLoaded())
{
reviveRewardedAd.Show();
}
}
...
}
This is a very simple and not optimize solution but this will solve your problem.
this is my code...
public class AutoLog : MonoBehaviourPunCallbacks
{
public void Connect()
{
if (!PhotonNetwork.IsConnected)
{
if (PhotonNetwork.ConnectUsingSettings())
{
log.text += "\nConnected to Server";
}
else
{
log.text += "\nFalling Connecting to Server";
}
}
}
public override void OnConnectedToMaster()
{
connect.interactable = false;
join.interactable = true;
}
............
public void JoinRandom()
{
if (!PhotonNetwork.JoinRandomRoom())
{
log.text += "\nFail Joinned Room";
}
}
any idea what can happen or how to solve
public override void OnJoinRandomFailed(short returnCode, string message)
{
log.text += "\nNo Rooms to Join, creating one...";
if(PhotonNetwork.CreateRoom(null, new Photon.Realtime.RoomOptions() { MaxPlayers = maxPlayer }))
{
log.text += "\nRoom Create";
}
else
{
log.text += "\nFail Creating Room";
}
}
public override void OnJoinedRoom()
{
log.text += "\nJoinned";
}
}
when 2 players enter they don't join the same room, each player creates another room.
I use Photon2 for unity.
any idea what can happen or how to solve
You can use this script and easily you will join you both players in a single room. This script is working on my project. make sure you set the Photon App ID which create from photon dashboard.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
public class AutoLog : MonoBehaviourPunCallbacks
{
string gameVersion = "1";
private byte maxPlayersPerRoom = 2;
public GameObject controlPanel;
public GameObject progressLabel;
bool isConnecting;
void Awake()
{
// #Critical
// this makes sure we can use PhotonNetwork.LoadLevel() on the master client and all clients in the same room sync their level automatically
PhotonNetwork.AutomaticallySyncScene = true;
}
void Start()
{
// Connect();
progressLabel.SetActive(false);
controlPanel.SetActive(true);
}
public void Connect()
{
isConnecting = true;
progressLabel.SetActive(true);
controlPanel.SetActive(false);
// we check if we are connected or not, we join if we are , else we initiate the connection to the server.
Debug.Log(PhotonNetwork.IsConnected);
if (PhotonNetwork.IsConnected)
{
// #Critical we need at this point to attempt joining a Random Room. If it fails, we'll get notified in OnJoinRandomFailed() and we'll create one.
PhotonNetwork.JoinRandomRoom();
}
else
{
// #Critical, we must first and foremost connect to Photon Online Server.
PhotonNetwork.GameVersion = gameVersion;
PhotonNetwork.ConnectUsingSettings();
Debug.Log("<color=green>Connected </color>");
}
}
public override void OnConnectedToMaster()
{
if (isConnecting)
{
Debug.Log(" OnConnectedToMaster() ");
// #Critical: The first we try to do is to join a potential existing room. If there is, good, else, we'll be called back with OnJoinRandomFailed()
PhotonNetwork.JoinRandomRoom();
}
}
public override void OnDisconnected(DisconnectCause cause)
{
PhotonNetwork.Disconnect();
Debug.LogWarningFormat("OnDisconnected()", cause);
// progressLabel.SetActive(false);
//controlPanel.SetActive(true);
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
Debug.Log("OnJoinRandomFailed() ");
// #Critical: we failed to join a random room, maybe none exists or they are all full. No worries, we create a new room.
PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = maxPlayersPerRoom });
}
public override void OnJoinedRoom()
{
Debug.Log(" OnJoinedRoom() ");
Debug.Log(PhotonNetwork.IsConnected);
if (PhotonNetwork.CurrentRoom.PlayerCount == 1)
{ PhotonNetwork.LoadLevel(1);
Debug.Log("Master Connected in Room");
// #Critical
// Load the Room Level.
}
if (PhotonNetwork.CurrentRoom.PlayerCount == 2)
{
PhotonNetwork.LoadLevel(1);
}
}
}
If you connect to Photon Cloud, make sure that all clients connect to the same virtual application (AppId + AppVersion) and connect to the same servers (same region).
Go through the "Matchmaking Checklist" carefully.
In unity I keep getting the error message "NullReferenceException: Object reference not set to an instance of an object" on this:
listOfBanks[0].Deposit(50);
and
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
I have 3 options listed in the drop down menu and when I Debug.Log the number of items in the array I get 3 as my count. But I can't do anything with them. The banks variable is set as the Dropdown object in the inspector as well as the accntBlnce as the text object in my panel.
The code is below.
Banks.cs
public class Banks : MonoBehaviour {
public Dropdown banks;
public Text accntBlnce;
public Bank[] listOfBanks;
public int curBank = 0;
void Start() {
listOfBanks = new Bank[banks.options.Count];
listOfBanks[0].Deposit(50);
}
void Update() {
curBank = banks.value;
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
}
}
Bank.cs
public class Bank{
public Bank() { }
public Bank(string orgn, float amntToRprt, float blnce) {
origin = orgn;
amountToReport = amntToRprt;
balance = blnce;
}
public string origin { get; set; }
public float amountToReport { get; set; }
public float balance { get; set; }
public bool Deposit(float amnt) {
if (amnt > 0) {
balance += amnt;
if(amnt > amountToReport) {
FlagForReport();
}
return true;
}
else
return false;
}
private void FlagForReport() {
throw new NotImplementedException();
}
public float GetBalance() {
return balance;
}
public bool Withdraw(float amnt) {
if (amnt > 0) {
if (balance >= amnt) {
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
public bool Transfer(float amnt, Bank bank) {
if (amnt > 0) {
if (balance >= amnt) {
if(bank.Deposit(amnt))
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
}
This is the fourth time array question is asked this week with the-same problem and the-same solution.
You declared the array here:
listOfBanks = new Bank[banks.options.Count];
but you did not create new instance of each Bank script before calling
listOfBanks[0].Deposit(50); and listOfBanks[curBank].GetBalance().ToString("c").
Declaring array and setting the size is NOT the-same as creating new instance of a script.
The solution is to loop through the array and create new instance of each one.
In your Banks.cs, replace the code in your Start() function with the one below:
void Start()
{
//Declare how much Bank array should be created
listOfBanks = new Bank[banks.options.Count];
//Now Create instance of each bank
for (int i = 0; i < listOfBanks.Length; i++)
{
//Create new instance of each Bank class
//listOfBanks[i] = new Bank();
listOfBanks[i] = new Bank("", 50, 50);
}
listOfBanks[0].Deposit(50);
}
May I ask for help with the following?
I am attempting to connect and control three pieces of household electronic equipment by computer through a GlobalCache GC-100 and iTach. As you will see in the following code, I created a class ("GlobalCacheAdapter") that can communicate and control the equipment, and created an instance of the class for each piece of equipment. Although each instance seems to work well with communicating and in controlling each piece of equipment, the *feedback returned from the equipment* seems only to be visible at the defining class level's - "ReaderThreadProc" procedure. Further processing of the feedback is required for each piece of equipment and I am uncertain as to how to forward this feedback at the equipment specific instance-level. I suspect that an instance-specific EventHandler will need to be implemented; however I am not aware as to how to implement this type of instance-specific EventHandler in order to complete processing and update the appropriate controls.
Any help wold be greatly appreciated.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// Create three new instances of GlobalCacheAdaptor and connect.
// GC-100 (Elan) 192.168.1.70 4998
// GC-100 (TuneSuite) 192.168.1.70 5000
// GC iTach (Lighting) 192.168.1.71 4999
private GlobalCacheAdaptor elanGlobalCacheAdaptor;
private GlobalCacheAdaptor tuneSuiteGlobalCacheAdaptor;
private GlobalCacheAdaptor lutronGlobalCacheAdaptor;
public Form1()
{
InitializeComponent();
elanGlobalCacheAdaptor = new GlobalCacheAdaptor();
elanGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 4998);
tuneSuiteGlobalCacheAdaptor = new GlobalCacheAdaptor();
tuneSuiteGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 5000);
lutronGlobalCacheAdaptor = new GlobalCacheAdaptor();
lutronGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.71"), 4999);
elanTextBox.Text = elanGlobalCacheAdaptor._line;
tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
}
private void btnZoneOnOff_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,4,1,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,800" + Environment.NewLine); }
private void btnSourceInput1_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,179,20,179,20,179,20,179,20,179,20,179,20,179,20,278,20,179,20,179,20,179,20,780" + Environment.NewLine); }
private void btnSystemOff_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,184,20,184,20,184,20,184,20,184,20,286,20,286,20,286,20,184,20,184,20,184,20,820" + Environment.NewLine); }
private void btnLightOff_Click(object sender, EventArgs e) { lutronGlobalCacheAdaptor.SendMessage("sdl,14,0,0,S2\x0d"); }
private void btnLightOn_Click(object sender, EventArgs e) { lutronGlobalCacheAdaptor.SendMessage("sdl,14,100,0,S2\x0d"); }
private void btnChannel31_Click(object sender, EventArgs e) { tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x31\x00\x30\x21\xB8\x0D"); }
private void btnChannel30_Click(object sender, EventArgs e) { tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x30\x00\x30\x21\xB8\x0D"); }
}
}
public class GlobalCacheAdaptor
{
public Socket _multicastListener;
public string _preferredDeviceID;
public IPAddress _deviceAddress;
public Socket _deviceSocket;
public StreamWriter _deviceWriter;
public bool _isConnected;
public int _port;
public IPAddress _address;
public string _line;
public GlobalCacheAdaptor() { }
public static readonly GlobalCacheAdaptor Instance = new GlobalCacheAdaptor();
public bool IsListening { get { return _multicastListener != null; } }
public GlobalCacheAdaptor ConnectToDevice(IPAddress address, int port)
{
if (_deviceSocket != null) _deviceSocket.Close();
try
{
_port = port;
_address = address;
_deviceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_deviceSocket.Connect(new IPEndPoint(address, port)); ;
_deviceAddress = address;
var stream = new NetworkStream(_deviceSocket);
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
_deviceWriter = writer;
writer.WriteLine("getdevices");
var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
readerThread.Start(reader);
_isConnected = true;
return Instance;
}
catch { DisconnectFromDevice(); MessageBox.Show("ConnectToDevice Error."); throw; }
}
public void SendMessage(string message)
{
try
{
var stream = new NetworkStream(_deviceSocket);
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
_deviceWriter = writer;
writer.WriteLine(message);
var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
readerThread.Start(reader);
}
catch { MessageBox.Show("SendMessage() Error."); }
}
public void DisconnectFromDevice()
{
if (_deviceSocket != null)
{
try { _deviceSocket.Close(); _isConnected = false; }
catch { MessageBox.Show("DisconnectFromDevice Error."); }
_deviceSocket = null;
}
_deviceWriter = null;
_deviceAddress = null;
}
**private void ReaderThreadProc(object state)**
{
var reader = (StreamReader)state;
try
{
while (true)
{
var line = reader.ReadLine();
if (line == null) break;
_line = _line + line + Environment.NewLine;
}
**// Feedback from each piece of equipment is visible here.
// Need to create EventHandler to notify the TextBoxes to update with _line**
}
catch { MessageBox.Show("ReaderThreadProc Error."); }
}
}
From my understanding of the question, you want to do something like this?
You need to know when a GlobalCacheAdapter updates and which one updated in order to update textboxes on a form. My question to you is this - do you actually need to know which updated?
If you declare in your class an event handler like this:
public class GlobalCacheAdaptor
{
public event EventHandler<EventArgs> Updated;
protected virtual void OnUpdated()
{
var handler = Updated;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void Foo()
{
// When an update is received, raise Updated event
OnUpdated();
}
}
Then in your form subscribe to Updated for all three GlobalCacheHandler instances
public Form1()
{
elanGlobalCacheAdaptor.Updated += (s,e) =>
{
elanTextBox.Text = elanGlobalCacheAdaptor._line;
}
tuneSuiteGlobalCacheAdaptor.Updated += (s,e) =>
{
tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
}
lutronGlobalCacheAdaptor.Updated += (s,e) =>
{
lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
}
}
You should be able to update the correct text box when the appropriate cache handler raises the Updated event.
Finally you may need to handle cross-thread interactions. if so, see this article on MSDN, particularly the part "Thread-Safe Calls to a Windows Forms Control"