vb.net - How to Declare new task as SUB with parameters - vb.net

As you know we have a new syntax in vb.net with possibility to create inline tasks so we could run it asynchronously.
This is the correct code:
Dim testDeclaring As New Task(Sub()
End Sub)
testDeclaring.Start()
but now I need to pass a parameter in the subroutine and I can't find correct syntax for that.
Is it possible any way?

It's not possible. However, you could just use the parameters from the current scope:
Public Function SomeFunction()
Dim somevariable as Integer = 5
Dim testDeclaring As New Task(Sub()
Dim sum as integer = somevariable + 1 ' No problems here, sum will be 6
End Sub)
testDeclaring.Start()
End Function

If you want to pass a parameter you could do this
Dim someAction As Action(Of Object) = Sub(s As Object)
Debug.WriteLine(DirectCast(s, String))
End Sub
Dim testDeclaring As New Task(someAction, "tryme")
testDeclaring.Start()

Dont know if you looking for this:
Dim t As Task = New Task(Sub() RemoveBreakPages(doc))
Sub RemoveBreakPages(ByRef doc As Document)
Dim paragraphs As NodeCollection = doc.GetChildNodes(NodeType.Paragraph, True)
Dim runs As NodeCollection = doc.GetChildNodes(NodeType.Run, True)
For Each p In paragraphs
If CType(p, Paragraph).ParagraphFormat().PageBreakBefore() Then
CType(p, Paragraph).ParagraphFormat().PageBreakBefore = False
End If
Next
End Sub
Regards.

Related

VB.NET Sub inside of a Function? What is this?

So I'm reading through my source code looking for places to improve the code when I come across this unholy chunk of code.
Public Function ReadPDFFile(filePath As String,
Optional maxLength As Integer = 0) As List(Of String)
Dim sbContents As New Text.StringBuilder
Dim cArrayType As Type = GetType(PdfSharp.Pdf.Content.Objects.CArray)
Dim cCommentType As Type = GetType(PdfSharp.Pdf.Content.Objects.CComment)
Dim cIntegerType As Type = GetType(PdfSharp.Pdf.Content.Objects.CInteger)
Dim cNameType As Type = GetType(PdfSharp.Pdf.Content.Objects.CName)
Dim cNumberType As Type = GetType(PdfSharp.Pdf.Content.Objects.CNumber)
Dim cOperatorType As Type = GetType(PdfSharp.Pdf.Content.Objects.COperator)
Dim cRealType As Type = GetType(PdfSharp.Pdf.Content.Objects.CReal)
Dim cSequenceType As Type = GetType(PdfSharp.Pdf.Content.Objects.CSequence)
Dim cStringType As Type = GetType(PdfSharp.Pdf.Content.Objects.CString)
Dim opCodeNameType As Type = GetType(PdfSharp.Pdf.Content.Objects.OpCodeName)
Dim ReadObject As Action(Of PdfSharp.Pdf.Content.Objects.CObject) = Sub(obj As PdfSharp.Pdf.Content.Objects.CObject)
Dim objType As Type = obj.GetType
Select Case objType
Case cArrayType
Dim arrObj As PdfSharp.Pdf.Content.Objects.CArray = DirectCast(obj, PdfSharp.Pdf.Content.Objects.CArray)
For Each member As PdfSharp.Pdf.Content.Objects.CObject In arrObj
ReadObject(member)
Next
Case cOperatorType
Dim opObj As PdfSharp.Pdf.Content.Objects.COperator = DirectCast(obj, PdfSharp.Pdf.Content.Objects.COperator)
Select Case System.Enum.GetName(opCodeNameType, opObj.OpCode.OpCodeName)
Case "ET", "Tx"
sbContents.Append(vbNewLine)
Case "Tj", "TJ"
For Each operand As PdfSharp.Pdf.Content.Objects.CObject In opObj.Operands
ReadObject(operand)
Next
Case "QuoteSingle", "QuoteDbl"
sbContents.Append(vbNewLine)
For Each operand As PdfSharp.Pdf.Content.Objects.CObject In opObj.Operands
ReadObject(operand)
Next
Case Else
'Do Nothing
End Select
Case cSequenceType
Dim seqObj As PdfSharp.Pdf.Content.Objects.CSequence = DirectCast(obj, PdfSharp.Pdf.Content.Objects.CSequence)
For Each member As PdfSharp.Pdf.Content.Objects.CObject In seqObj
ReadObject(member)
Next
Case cStringType
sbContents.Append(DirectCast(obj, PdfSharp.Pdf.Content.Objects.CString).Value)
Case cCommentType, cIntegerType, cNameType, cNumberType, cRealType
'Do Nothing
Case Else
Throw New NotImplementedException(obj.GetType().AssemblyQualifiedName)
End Select
End Sub
Using pd As PdfSharp.Pdf.PdfDocument = PdfSharp.Pdf.IO.PdfReader.Open(filePath, PdfSharp.Pdf.IO.PdfDocumentOpenMode.ReadOnly)
For Each page As PdfSharp.Pdf.PdfPage In pd.Pages
ReadObject(PdfSharp.Pdf.Content.ContentReader.ReadContent(page))
If maxLength > 0 And sbContents.Length >= maxLength Then
If sbContents.Length > maxLength Then
sbContents.Remove(maxLength - 1, sbContents.Length - maxLength)
End If
Exit For
End If
sbContents.Append(vbNewLine)
Next
End Using
'Return sbContents.ToString
Dim ReturnList As New List(Of String)
For Each Line In sbContents.ToString.Split(vbNewLine)
If String.IsNullOrWhiteSpace(Line.Trim) Then
Else
ReturnList.Add(Line.Trim)
End If
Next
Return ReturnList
End Function
All this does is read the text parts of a PDF using PDFSharp. What caught my eye however was line 17. Is that a Sub inside of the function?
So, what exactly is this Sub inside of a function? I didn't write this code so I've never seen anything like this before.
How does this work exactly and why wouldn't I use a function to do the processing and then return the results?
In short, my question is, what is this, how does it work, and why would I want to use something like this?
That's a so-called Lambda expression. They're used to create inline (or more correctly: in-method) methods, which makes them more dynamic than normal methods.
In your example a lambda expression is not necessary and only makes the code harder to understand. I suppose the author of that code wrote a lambda expression instead of a separate method in order to not expose ReadObject to any outside code.
One of the best uses for a lambda expression IMO is when you want to make thread-safe calls to the UI thread, for instance:
If Me.InvokeRequired = True Then
Me.Invoke(Sub() TextBox1.Text = "Process complete!")
Else
TextBox1.Text = "Process complete!"
End If
...where the same code without a lambda would look like this:
Delegate Sub UpdateStatusTextDelegate(ByVal Text As String)
...somewhere else...
If Me.InvokeRequired = True Then
Me.Invoke(New UpdateStatusTextDelegate(AddressOf UpdateStatusText), "Process complete!")
Else
UpdateStatusText("Process complete!")
End If
...end of somewhere else...
Private Sub UpdateStatusText(ByVal Text As String)
TextBox1.Text = Text
End Sub
There are also other examples where lambda expressions are useful, for instance if you want to initialize a variable but do some processing at first:
Public Class Globals
Public Shared ReadOnly Value As Integer = _
Function()
DoSomething()
Dim i As Double = CalculateSomething(3)
Return Math.Floor(3.45 * i)
End Function.Invoke()
...
End Class
Yet another usage example is for creating partially dynamic event handlers, like this answer of mine.

visual basic multiple input boxes i only need 1

Why do I keep getting two input boxes instead of one? What am I doing wrong? Is it how I am passing values through functions? If so, how can I fix this?
Private Sub Calculate_Click(sender As Object, e As EventArgs) Handles Calculate.Click
'Dim ready_ship As Integer = GetInStock()
Dim display_spools As Integer = ReadyToShip()
Dim display_backOrders As Integer = BackOrdered()
lbl_rship.Text = display_spools.ToString()
lbl_backo.Text = display_backOrders.ToString()
End Sub
Function GetInStock() As Integer
Dim amount_Spools As String = Nothing
amount_Spools = InputBox(" Enter the number of spools currently in stock: ")
Return CInt(amount_Spools)
End Function
Function ReadyToShip() As Integer
Dim ready_ship As Integer = GetInStock()
Dim a As Integer
a = CInt(ready_ship)
Return a
End Function
Function BackOrdered() As Integer
Dim b As Integer = ReadyToShip()
Dim c As Integer
c = b - CInt(TextBox1.Text)
Return c
End Function
End Class
Your Calculate_Click event is calling ReadyToShip() and BackOrdered() functions which are both going to GetInStock() function, which is displaying the input box. So it will be displayed twice.
This class would be better served using properties, they are easier to manage and will help avoid this kind of method duplication.

How to use a Sub value in a second Sub

I am new to VB.net and really need bigger brains for this:
(all code added in one module)
I have a random function (that is giving me a random text value).
This is how I call the random function:
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
Now, I have a Sub that takes the Random text value and displays that in a Richtextbox, with a typewriter effect:
Sub type()
Dim thread As New Thread(AddressOf voice)
thread.Start()
Form1.RichTextBox1.Refresh()
Form1.count_ = 1
Form1.RichTextBox1.Text = Form1.str_
Form1.RichTextBox1.Clear()
Form1.str_ = RandomIpAddress
Form1.Timer1.Enabled = True
End Sub
I also have a Thread that I want to call in Sub Type()
Private Sub voice()
Dim TheSpeaker As New Speech.Synthesis.SpeechSynthesizer()
TheSpeaker.SelectVoiceByHints(Synthesis.VoiceGender.Female)
TheSpeaker.Speak(RandomIpAddress)
End Sub
My problem is: how to get the RandomIpAddress in both Sub type() and Private Sub voice?
If I'm using the:
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
inside the Module, then my code is running ONCE correctly. After that the Random code is not working any more (it's loading the same text) - never changing the result (no random).
If I am going to move the "Dim" code inside SUB and Thread, then I will have a random text added in richtextbox and another in Thread. So is doing a random result for both. I just want to get the same random result in both!
Here is my full code:
Imports System.Threading
Imports System.Speech
Imports System.Speech.Recognition
Module brain
Public str_ As String
Private rdm As New Random
Private Function GetRandom(max As Integer) As Integer
If InStr(UCase(Form1.TextBox1.Text), "HELLO MOTHER") Then
Dim theTime As DateTime
theTime = Now.ToLongTimeString
If theTime >= #6:00:00 AM# AndAlso theTime <= #9:59:59 AM# Then
Return rdm.Next(0, 3)
Else
Return rdm.Next(3, 6)
End If
End If
If InStr(UCase(Form1.TextBox1.Text), "HOW ARE YOU") Then
Return rdm.Next(6, 8)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHO ARE YOU") Then
Return rdm.Next(8, 11)
End If
If InStr(UCase(Form1.TextBox1.Text), "YOUR NAME") Then
Return rdm.Next(11, 13)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT ARE YOU") Then
Return rdm.Next(13, 16)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT DO YOU DO") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "WHAT CAN YOU DO") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "HELP ME") Then
Return rdm.Next(16, 18)
End If
If InStr(UCase(Form1.TextBox1.Text), "YOUR MISSION") Then
Return rdm.Next(18, 19)
End If
End Function
Dim IpAddresses As String() = My.Resources.BrainAnswer.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim RandomIpAddress As String = IpAddresses(GetRandom(IpAddresses.Length))
Sub type()
Dim thread As New Thread(AddressOf voice)
thread.Start()
Form1.RichTextBox1.Refresh()
Form1.count_ = 1
Form1.RichTextBox1.Text = Form1.str_
Form1.RichTextBox1.Clear()
Form1.str_ = RandomIpAddress
Form1.Timer1.Enabled = True
End Sub
Private Sub voice()
Dim TheSpeaker As New Speech.Synthesis.SpeechSynthesizer()
TheSpeaker.SelectVoiceByHints(Synthesis.VoiceGender.Female)
Dim cleanString As String = Replace(RandomIpAddress, ".", " ")
TheSpeaker.Speak(cleanString)
End Sub
End Module
It seems either you are not getting your task clear or not getting us clear about it.
There is a handful of remarks to pay for this strip of code
Your variable max isn't used in your function GetRandom, that is not a foretelling sign in favor of same function's results.
I believe you are missing Return rdm.Next(19, max) somewhere in your GetRandom(max) function, just a prediction that has a strong likelihood to be applicable
RandomIpAddress is declared a static variable, while you are using it as a function.
Public Delegate Function newfunction() as string
Public RandomIpAddress As newfunction = Function() IpAddresses(GetRandom(IpAddresses.Length))
Thus the use of it would differ to:
Form1.str_ = RandomIpAddress()
And
Dim cleanString As String = Replace(RandomIpAddress(), ".", " ")
Threads are independant entities, they dont have access to other forms' ressources unless you share them.
Declaration of your textbox must be:
Friend Shared WithEvents TextBox1 As TextBox .

Setting Values Using Reflection

I am using VB.NET. I have created a small scale test project that works similar to my program. I am trying to say something like: getObjectType(object1) if Object1.getType() = "ThisType" then get the properties. Each object contains an ID and I would like to do this: Object1.Id = -1 (I know it won't be that short or easy). I thought there was a way to do this by using something like: Object1.SetValue(Value2Change, NewValue) but that doesn't work and I'm not sure how to exactly do this. Below is my code. Thank You!
Module Module1
Sub Main()
Dim Db As New Luk_StackUp_ProgramEntities
Dim Obj1 As IEnumerable(Of Stackup) = (From a In Db.Stackups).ToList
Dim Obj2 As IEnumerable(Of Object) = (From a In Db.Stackups).ToList
Dim IdNow As Integer = Obj1(0).IdStackup
Dim StackUpNow As Stackup = (From a In Db.Stackups Where a.IdStackup = IdNow).Single
Console.WriteLine(StackUpNow)
getInfo(StackUpNow)
getInfo(Obj1(0), Obj1(0))
areObjectsSame(Obj1(0), Obj1(67))
switchObjects(Obj1(0), Obj2(1))
getObjectValues(Obj2(55))
Console.WriteLine("========================================")
TestCopyObject(StackUpNow)
ChangeObjectValues(StackUpNow)
Console.ReadKey()
End Sub
Private Sub ChangeObjectValues(Object1 As Object)
Console.WriteLine("Changing Object Values")
Dim myField As PropertyInfo() = Object1.GetType().GetProperties()
'Dim Index As Integer 'Did not find value
'For Index = 0 To myField.Length - 1
' If myField(Index).ToString.Trim = "IdStackup" Then
' Console.WriteLine("Found the ID")
' End If
'Next
If Object1.GetType().Name = "Stackup" Then
'Set the Value
End If
End Sub
You can use PropertyInfo.SetValue to set the value using reflection. You could also use a LINQ SingleOrDefault query to simplify finding the correct PropertyInfo, so you could do something like this:
Private Sub ChangeObjectValues(Object1 As Object)
Console.WriteLine("Changing Object Values")
Dim t As Type = Object1.GetType()
If t.Name = "Stackup" Then
Dim myField As PropertyInfo = t.GetProperties() _
.SingleOrDefault(Function(x) x.Name = "IdStackup")
If myField IsNot Nothing Then
Console.WriteLine("Found the ID")
myField.SetValue(Object1, -1)
End If
End If
End Sub
It's not clear from the question if you really need to use reflection - perhaps a common interface to define the id property, or just type checking and casting, etc. would be better.
Well, I struggled to see how your code example applied to your question, but if you are simply asking how to set the ID of an object using reflection, this code might help you. The trick is that a property is typically handled using a set and a get method.
Imports System.Web.UI.WebControls
Imports System.Reflection
Module Module1
Sub Main()
Dim tb As New Label()
Dim t As Type = tb.GetType()
If TypeOf tb Is Label Then
Dim mi As MethodInfo = t.GetMethod("set_ID")
mi.Invoke(tb, New Object() {"-1"})
End If
Console.WriteLine(tb.ID)
Console.ReadLine()
End Sub
End Module

read specific values from text file

I have the following visual basic code, which is part of a custom class. I want a simple and effective way(use little computer resources) to assign the "value1" value(100) to "_field1","value2" value(8) to "_field2" etc. Any nice ideas? thanks
Private Sub readcrnFile()
'read files and assing values to the properties
Dim sr As New IO.StreamReader(_fileName)
_field1 = sr.ReadToEnd()
_field2 = sr.ReadToEnd()
_field3 = sr.ReadToEnd()
sr.Close()
End Sub
where _fileName is a full path to a text file which looks like this:
value1: 100
value2: 8
value3: 80
Private Sub readcrnFile()
Dim lines = File.ReadLines(_fileName)
For Each line In lines
Dim val = line.Split(":")(1).Trim
'do something with val?
Next
End Sub
Returning a dictionary is trivial:
Private Sub readcrnFile()
Dim dict = File.ReadLines(_fileName).Select(Function(line) line.Split(":")).ToDictionary(Function(parts) parts(0).Trim, Function(parts) parts(1).Trim)
Debug.WriteLine(dict("value1")) 'will print 100
End Sub
Change your _field1, _field2 and _field3 variables to a List(Of String) (i.e. named field) and access to each field using its index (field(0), field(1), field(2)).
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(_filename)
For i = 1 To 3
If line.Contains("value" & i) Then
field.Add(line.Substring(line.IndexOf(":") + 2))
End If
Next
Next
End Sub