|
Which version of C# / Visual Studio are you using?
private void TestFunction(object unknownClass)
{
(MyBase localObject, string specificProperty) = unknownClass switch
{
ClassOne c1 => (c1, c1.ClassOneProperty),
ClassTwo c2 => (c2, c2.ClassTwoProperty),
MyBase b => (b, null),
_ => (null, null),
};
if (localObject is null)
{
Console.WriteLine($"Unknown object: {unknownClass}");
}
else
{
Console.WriteLine($"Common Property = {localObject.CommonProperty}, Specific Property = {specificProperty}.");
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
string s1, s2;
if ( unknownClass is MyBase myBase ) {
s1 = myBase.CommonProperty;
if ( unknownClass is ClassOne one ) {
s2 = one.ClassOneProperty;
} else if ( unknownClass is ClassTwo two ) {
s2 = two.ClassTwoProperty;
}
}
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
How to trigger an event when the last data was read from COM port after a certain time with C#?
Is it possible?
|
|
|
|
|
No really - you only get an Event with new incomming data.
But if you know with which characters your transmission ends you can check this in your Received-Event and you can raise your own (self-created) Event.
|
|
|
|
|
There is no specific way to do that, but if you set up a Timer with a half second interval and a DateTime variable that you compare in it's Tick event against the current time, you can spot it. Then all you need is to set the variable to the current date and time plus your timeout duration each time you process a character from the port.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
It is possible with a timer. I did it in Visual Basic before to send SMS and it was delivered using my phone as gateway, I raised event Sending, see the VB Code and the C# equivalent below-:
'VB
Private Sub ReadPort()
Dim SerialIn As String = Nothing
Dim RXBuffer(SMSPort.ReadBufferSize) As Byte
Dim SMSMessage As String = Nothing
Dim Strpos As Integer = 0
Dim TmpStr As String = Nothing
While SMSPort.IsOpen = True
If (SMSPort.BytesToRead <> 0) And (
SMSPort.IsOpen = True) Then
While SMSPort.BytesToRead <> 0
SMSPort.Read(RXBuffer, 0, SMSPort.ReadBufferSize)
SerialIn =
SerialIn & System.Text.Encoding.ASCII.GetString(
RXBuffer)
If SerialIn.Contains(">") = True Then
_ContSMS = True
End If
If SerialIn.Contains("+CMGS:") = True Then
_Continue = True
RaiseEvent Sending(True)
_Wait = False
SerialIn = String.Empty
ReDim RXBuffer(SMSPort.ReadBufferSize)
End If
End While
RaiseEvent DataReceived(SerialIn)
SerialIn = String.Empty
ReDim RXBuffer(SMSPort.ReadBufferSize)
End If
End While
End Sub
//=======================================================================
//CSharp
private void ReadPort()
{
string SerialIn = null;
byte[] RXBuffer = new byte[SMSPort.ReadBufferSize + 1];
string SMSMessage = null;
int Strpos = 0;
string TmpStr = null;
while (SMSPort.IsOpen == true)
{
if ((SMSPort.BytesToRead != 0) & (SMSPort.IsOpen == true))
{
while (SMSPort.BytesToRead != 0)
{
SMSPort.Read(RXBuffer, 0, SMSPort.ReadBufferSize);
SerialIn = SerialIn + System.Text.Encoding.ASCII.GetString(RXBuffer);
if (SerialIn.Contains(">") == true)
_ContSMS = true;
if (SerialIn.Contains("+CMGS:") == true)
{
_Continue = true;
Sending?.Invoke(true);
_Wait = false;
SerialIn = string.Empty;
RXBuffer = new byte[SMSPort.ReadBufferSize + 1];
}
}
DataReceived?.Invoke(SerialIn);
SerialIn = string.Empty;
RXBuffer = new byte[SMSPort.ReadBufferSize + 1];
}
}
}
You can manipulate the code above and add a timer control for timing.
|
|
|
|
|
I have an app in csharp dot net version 4.7.1 and moving to dotnet version 6.
The snippet of code from 4.7.1 is
Quote: using System.Web; // requires a reference to System.Web.dll
using System.Web.Configuration; // requires a reference to System.Configuration.dll
///
/// Imports an xml store by it's relative path in ASP.NET and returns the requested connection.
/// Does not open the connection.
///
/// <param name="httpContext" />Context of HTTP request to resolve relative path with. (e.g. HttpContext.Current)
/// <param name="configurationFileName" />Full or relative server path. (e.g. ~/App_Data/databases.xml)
/// <param name="connectionName" />Returns a new instance of the provider's class that represents a connection to the database.
public static DbConnection Open(HttpContextBase httpContext, string configurationFileName, string connectionName)
{
DbConnection connection = Connection(httpContext, configurationFileName, connectionName);
connection.Open();
return connection;
}
///
/// Imports an xml store by it's relative path in ASP.NET and returns the requested connection.
/// Does not open the connection.
///
/// <param name="httpContext" />Context of HTTP request to resolve relative path with. (e.g. HttpContext.Current)
/// <param name="configurationFileName" />Full or relative server path. (e.g. ~/App_Data/databases.xml)
/// <param name="connectionName" />Returns a new instance of the provider's class that represents a connection to the database.
/// <returns>Returns a new instance of the provider's class that represents a connection to the database.
public static DbConnection Connection(HttpContextBase httpContext, string configurationFileName, string connectionName)
{
Sources.ImportXmlStore(httpContext.Server.MapPath(configurationFileName));
return Connection(connectionName);
}
I cannot use
using System.Web;
using System.Web.Configuration;
as these don't exist in 6.0 so would appreciate help on how to convert the following to keep the same functionality.
Quote: DbConnection connection = Connection(httpContext, configurationFileName, connectionName);
and
Quote: public static DbConnection Connection(HttpContextBase httpContext, string configurationFileName, string connectionName)
Many thanks for any help.
|
|
|
|
|
DbConnection is in the System.Data.Common namespace; i.e.
using System.Data.Common;
DbConnection Class (System.Data.Common) | Microsoft Docs
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Hi Gerry
Thank you for your reply but that is not the issue. I have that issue is the following is not in 6.0
I have the following at the beginning of my code.
Quote: using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Xml.Linq;
using System.Security.Cryptography;
using System.Web; // requires a reference to System.Web.dll
using System.Web.Configuration; // requires a reference to System.Configuration.dll
I cannot find a reference to items in bold so looking for how to reproduce the same functionality System.Web.Configuration was required for HttpContextBase and WebConfigurationManager
Quote: using System.Web.Configuration; // requires a reference to System.Configuration.dll
HttpContextBase httpContext
ConnectionString = WebConfigurationManager.ConnectionStrings[name].ConnectionString
|
|
|
|
|
|
|
The while loop stop when data reads x, but the buttonTransfer button never gets enabled
and the MessageBox message never shows up, but the program does not either freeze. What can be the problem with this code?
try
{
buttonTransfer.Enabled = false;
port = new SerialPort();
port.BaudRate = 9600;
port.PortName = getValueNew;
port.Open();
port.Write("1");
while (data != "x")
{
data = port.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
buttonTransfer.Enabled = true;
MessageBox.Show("Done!");
port.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
|
|
|
|
|
What makes you think that the data you recieve is ever just "x"? Since you are using ReadLine, that call will block until a newline character is entered - the ReadLine will then strip it off, but it is required for your code to work.
I'd start with the debugger, and try following exactly what is happening before I went any further.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I will suggest you put a breakpoint on code line below and step through....
buttonTransfer.Enabled = true;
Your code may not be getting to that point as you assumed. If it gets to that point and your button is a physical object on your form, it must work.
|
|
|
|
|
Three comments:
1.
You should have told us where the code shown is sitting: in some event handler? in a BackGroundWorker's DoWork handler? where?
I can only hope it is not inside a DataReceived handler...
2.
Immediately displaying everything that ReadLine returns would probably be sufficient to find out what goes wrong and when.
3.
A simple "x" will not stop the loop, as ReadLine always waits for a line terminator (actually SerialPort.NewLine, which by default is said to equal Environment.NewLine). Is your peripheral sending "x\n" or "x\n\r" or some such?
Luc Pattyn [My Articles]
The Windows 11 "taskbar" is disgusting. It should be at the left of the screen, with real icons, with text, progress, etc. They downgraded my developer PC to a bloody iPhone.
modified 12-Apr-22 13:15pm.
|
|
|
|
|
All our applications are Web applications that depend heavily on Web Forms.
We have very serious challenge moving our applications to Blazor (Razor Pages). We used Oledb objects and data tables a lot and migrating is a big issue. No web forms in latest visual studio versions.
Does anyone have a quick fix? I will appreciate your help.
|
|
|
|
|
Raphael Adeniji wrote: No web forms in latest visual studio versions. Which version(s) are you referring to? They are definitely available in VS2019.
|
|
|
|
|
I meant Dot Net Core, they are surely available in Frameworks, but not in Dot Net Core.
|
|
|
|
|
|
I am working with SharpCompress and creating a parser that creates objects mimicking real folder structures to use in various browsable controls. Since the IEntry and IArchiveEntry interfaces in SharpCompress have all the makings of an "info" class, I have created two custom Info classes derived from System.IO.FileSystemInfo. Because most of the properties are NOT virtual, I have to use the new keyword to override them so that I can grab the info from the Entry object instead of the file system.
I want to use the base class FileSystemInfo to supply much of the data for my virtual file system object class. However, I am not sure if using the FileSystemInfo object will work with the derived classes that hide the original properties. Check the relevant part of my code below:
public class IOObjectNode : TreeNode;
{
FileSystemInfo info;
FileInfo file;
DirectoryInfo folder;
ArchiveDirectoryInfo virtualFolder;
ArchiveFileInfo virtualFile;
IEntry entry;
public string FileName { get { return info.Name; } }
public string Path { get { return System.IO.Path.GetDirectoryName(info.FullName); } }
public string FullName { get { return info.FullName; } }
public DateTime LastWriteTime { get { return info.LastWriteTime; } }
public DateTime CreationTime { get { return info.CreationTime; } }
public long Size { get { if (file != null) return file.Length; else return 0; } }
public long Length { get { return Size; } }
public IOObjectNode() { }
public void Populate(IEntry entry) { SharpEntry = entry; }
public void Populate(FileSystemInfo info) { ShellInfo = info; }
public FileSystemInfo ShellInfo
{
get { return info; }
protected set
{
info = value;
file = value as FileInfo;
folder = value as DirectoryInfo;
virtualFolder = value as ArchiveDirectoryInfo;
virtualFile = value as ArchiveFileInfo;
UpdateResources();
}
}
public IEntry SharpEntry
{
get { return entry; }
protected set
{
entry = value;
UpdateResources();
}
}
}
Notice my use of "info" in some of the properties above. Will this work with my custom class instances when info is the base class?
|
|
|
|
|
Nevermind. Found the answer myself with a few test classes:
public class CoreClass
{
public int Value { get { return 1; } }
}
public class ClassA : CoreClass
{
public new int Value { get { return 2; } }
}
public class ClassB : CoreClass
{
public new int Value { get { return 3; } }
}
public class ClassC : CoreClass
{
public new int Value { get { return 4; } }
}
public class ClassD : CoreClass
{
public new int Value { get { return 5; } }
}
public class ContainerClass
{
public CoreClass CoreObject { get; set; }
public int CoreValue { get { return CoreObject.Value; } }
public ContainerClass(CoreClass instance) { CoreObject = instance; }
}
static void Main(string[] args)
{
ContainerClass a = new ContainerClass(new ClassA());
ContainerClass b = new ContainerClass(new ClassB());
ContainerClass c = new ContainerClass(new ClassC());
ContainerClass d = new ContainerClass(new ClassD());
int av = a.CoreValue;
int bv = b.CoreValue;
int cv = c.CoreValue;
int dv = d.CoreValue;
}
Bummer... all the int values in Main were 1. So looks like it calls the base class method and not the derived one. Looks like I will need to try a different approach.
|
|
|
|
|
|
Well you can't override non-virtual/abstract methods or properties and I can't change Microsoft's base classes. Pretty annoying because it would be a simple solution to a now a more complex problem. I am guessing I will have to make a wrapper.
|
|
|
|
|
When I pushed the Transfer button a second time, I get the this error message, System.InvalidOperationException: 'This BackgroundWorker is currently busy and cannot run multiple tasks concurrently.' Can someone help me with this problem?
private void buttonTransfer_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.CancelAsync();
MessageBox.Show("Running!");
}
richTextBoxViewStatus.Clear();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
port.Close();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.CancelAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
do some work
}
|
|
|
|
|