How to call multiple different methods simultaneously - asp.net

I have some different methods that each import products from different sites.
If I execute these sequentially the entire process takes a lot of time, particularly when 1 method is running on a site that is less responsive.
I'd rather run them simultaneously.
This is what I have so far with 1 example method:
Public Class feedParameters
Private _productIdPrefix As String
Private _publishersite As String
Private _feedURL As String
Public Property productIdPrefix() As String
Get
Return _productIdPrefix
End Get
Set(value As String)
_productIdPrefix = value
End Set
End Property
Public Property publishersite() As String
Get
Return _publishersite
End Get
Set(value As String)
_publishersite = value
End Set
End Property
Public Property feedURL() As String
Get
Return _feedURL
End Get
Set(value As String)
_feedURL = value
End Set
End Property
End Class
Dim fpm As New feedParameters
fpm.publishersite = "mypublisher.nl"
fpm.feedURL = "http://www.domain.com/test.xml"
fpm.productIdPrefix = "10"
Protected Sub ImportProductsPublisherA(ByVal productIdPrefix As String, ByVal publishersite As String, ByVal feedURL As String)
End Sub
I tried this:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsPublisherA()), fpm)
Then I get 3 errors that I have not specified arguments for the 3 parameters: productIdPrefix, publishersite and feedURL
I also tried:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsPublisherA), fpm)
I get this error:
Method 'Protected Sub ImportProductsPublisherA(productIdPrefix As String, publishersite As String, feedURL As String)' does not have a signature compatible with delegate 'Delegate Sub WaitCallback(state As Object)'.
Any help is greatly appreciated!

using System.Threading.Tasks;
namespace Foo
{
public class Bar
{
public void ImportProductsSiteA() { }
public void ImportProductsSiteB() { }
public void ImportProductsSiteC() { }
public void ImportProductsSiteD() { }
public void Execute()
{
var a = Task.Factory.StartNew(ImportProductsSiteA);
var b = Task.Factory.StartNew(ImportProductsSiteB);
var c = Task.Factory.StartNew(ImportProductsSiteC);
var d = Task.Factory.StartNew(ImportProductsSiteD);
Task.WaitAll(a, b, c, d);
}
}
}

Is this WinForms or asp.net?
If winforms create a background worker for each function and start all of them, they will work independently in a separate thread.
If asp.net you want to look at using System.Threading.ThreadPool - http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteA))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteB))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteC))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteD))
If you functions take any parameters you can pass them like this:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteA), parameter-here)

Related

JsonConvert.DeserializeObject Returns missing values

I am attempting to push data through AJAX to my ASP.NET Web Service, which inserts the data into my DB. However, i am having problems looping through my deserialized list.
Here is my class:
Public Class TimesheetDetails
Inherits System.Web.Services.WebService
Public Property TimesheetID() As String
Get
Return m_TimesheetID
End Get
Set
m_TimesheetID = Value
End Set
End Property
Private m_TimesheetID As String
Public Property LineNumber() As String
Get
Return m_LineNumber
End Get
Set
m_LineNumber = Value
End Set
End Property
Private m_LineNumber As String
Public Property ProjectCode() As String
Get
Return m_ProjectCode
End Get
Set
m_ProjectCode = Value
End Set
End Property
Private m_ProjectCode As String
Public Property Comments() As String
Get
Return m_Comments
End Get
Set
m_Comments = Value
End Set
End Property
Private m_Comments As String
Public Property SAT() As Decimal
Get
Return m_SAT
End Get
Set
m_SAT = Value
End Set
End Property
Private m_SAT As Decimal
Public Property SUN() As Decimal
Get
Return m_SUN
End Get
Set
m_SUN = Value
End Set
End Property
Private m_SUN As Decimal
Public Property MON() As Decimal
Get
Return m_MON
End Get
Set
m_MON = Value
End Set
End Property
Private m_MON As Decimal
Public Property TUE() As Decimal
Get
Return m_TUE
End Get
Set
m_TUE = Value
End Set
End Property
Private m_TUE As Decimal
Public Property WED() As Decimal
Get
Return m_WED
End Get
Set
m_WED = Value
End Set
End Property
Private m_WED As Decimal
Public Property THU() As Decimal
Get
Return m_THU
End Get
Set
m_THU = Value
End Set
End Property
Private m_THU As Decimal
Public Property FRI() As Decimal
Get
Return m_FRI
End Get
Set
m_FRI = Value
End Set
End Property
Private m_FRI As Decimal
Public Property TOTAL() As Decimal
Get
Return m_TOTAL
End Get
Set
m_TOTAL = Value
End Set
End Property
Private m_TOTAL As Decimal
End Class
and the method
<WebMethod()>
Public Function SaveData(empdata) As String
'WebMethod to Save the data
Dim serializeData = JsonConvert.DeserializeObject(Of List(Of TimesheetDetails))(empdata)
Dim ids As String = ""
For Each obj As Object In serializeData
If obj.LineNumber = "0" Then
Else
Dim timesheetid As String = obj.TimesheetID
Dim linenumber As String = obj.LineNumber
Dim projectcode As String = obj.ProjectCode
Dim comments As String = obj.Comments
Dim monday As String = obj.MON
Dim tuesday As String = obj.TUE
Dim wednesday As String = obj.WED
Dim thursday As String = obj.THU
Dim friday As String = obj.FRI
Dim saturday As String = obj.SAT
Dim sunday As String = obj.SUN
Dim total As String = obj.TOTAL
Dim noteid As String = "No id found"
Debug.WriteLine(linenumber + " | " + projectcode + ", " + monday + tuesday + wednesday + thursday + friday + saturday + sunday)
End If
Next
Return Nothing
End Function
The data arrives from the AJAX post intact, but when the data is deserialized, some of my values remain the same, but others become null or 0.
Here are the before values, successfully posted:
[
{
"timesheetid":"86",
"linenumber":0
},
{
"timesheetid":"86",
"linenumber":1,
"projectcode":"12988",
"comments":" test comment",
"monday":"7.5",
"tuesday":"7.5",
"wednesday":"7.5",
"thursday":"7.5",
"friday":"7",
"saturday":"7.5",
"sunday":"7.5",
"total":"52"
}
]
and here are the values after the data is deserialized:
[
{
"timesheetid":"86",
"linenumber":0
},
{
"timesheetid":"86",
"linenumber":1,
"projectcode":"12988",
"comments":" test comment",
"monday":"0",
"tuesday":"0",
"wednesday":"0",
"thursday":"0",
"friday":"0",
"saturday":"0",
"sunday":"0",
"total":"52"
}
]
I think the problem is some properties of TimesheetDetails class is different with posted object properties. For example, property in posted object is name monday, while in TimesheetDetails class, its name is MON.

How can I assign a property value based on another property in a composite control?

Environment: Asp.net 4.5, Webforms
I'm creating a composite control. I've exposed multiple public properties, but running into a slight problem.
Let's say I have two properties:
Public Property Path() As String
Get
Return ViewState("Path")
End Get
Set(ByVal Value As String)
If UseAbsolute = True Then
' do something
Else
' it always lands heere...
End If
End If
ViewState("Path") = Value
End Set
End Property
Private _Path As String = String.Empty
Public Property UseAbsolute() As Boolean
....
End Property
Private _UseAbsolute As Boolean = False
My controls are being assigned values on PreRender. The problem is, when I call "Path" it's getting the default/private value for UseAbsolute. So even if I set the property to True in the control/html, it grabs the false first.
I can work around this many ways, but I feel I'm missing a proper method or understanding.
UPDATE
I forgot to mention. I am:
EnsureChildControls()
in the PreRender...
I also tried adding this to the properties themselves.
Shouldn't Your code be like this instead of how you have it?
Private _Path As String = String.Empty
Private _UseAbsolute As Boolean = False
'
Public Property Path() As String
Get
Return _Path
End Get
Set(ByVal Value As String)
If UseAbsolute = True Then
' do something
_Path = some_absolute_path
Else
' do something else
_Path = some_relative_path
End If
End Set
End Property
'
Public Property UseAbsolute () As Boolean
Get
Return _UseAbsolute
End Get
Set(ByVal Value As Boolean)
_UseAbsolute = Value
End Set
End Property

Convert ASCII Character Code to Character in VB.NET

I have a value I am pulling into a string that looks like this:
M'arta
I need to have it to translate the numeric value into an actual value so that the string looks like this:
M'arta
Any ideas on how to accomplish this in VB.NET? Here is the relevant line of code that returns this result:
Dim occupant as String = GridView1.Rows(e.RowIndex).Cells(2).Text
Below is the VB (& C#) version to what you're asking. Basically, use the MatchEvaluator argument in the Regex method to allow custom parsing of the matches. In this case, we find any instances of #<1-3_digit_number> we want to strip the `# symbol, and convert the decimal code.
I added a second conversion in your string (#116) just for testing purposes. You could refactor this in to a custom method and (not sure if VB has it) lambda expression to make it universal, but I'll leave that up to you.
VB.NET Version (DEMO)
Imports System.Text.RegularExpressions
Public Class Test
Public Shared Sub Main()
Dim sample As [String] = "M#39ar#116a"
Dim reg As New Regex("\x23\d{1,3}")
Console.WriteLine(reg.Replace(sample, New MatchEvaluator(AddressOf ReplaceASCIICode)))
End Sub
Public Shared Function ReplaceASCIICode(m As Match) As [String]
Dim code As Int32 = Int32.Parse(m.Value.Substring(1))
Return Convert.ToString(ChrW(code))
End Function
End Class
C# Version (DEMO)
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
String sample = "M#39ar#116a";
Regex reg = new Regex(#"\x23\d{1,3}");
Console.WriteLine(reg.Replace(sample, new MatchEvaluator(ReplaceASCIICode)));
}
public static String ReplaceASCIICode(Match m)
{
Int32 code = Int32.Parse(m.Value.Substring(1));
return Convert.ToString((char)code);
}
}
For archival purposes, here are the versions that support &#___; below:
VB.NET (DEMO)
Imports System.Text.RegularExpressions
Public Class Test
Public Shared Sub Main()
Dim sample As [String] = "M'arta"
Dim reg As New Regex("&#(\d{1,3});")
Console.WriteLine(reg.Replace(sample, New MatchEvaluator(AddressOf ReplaceASCIICode)))
End Sub
Public Shared Function ReplaceASCIICode(m As Match) As [String]
Dim code As Int32 = Int32.Parse(m.Groups(1).Value)
Return Convert.ToString(ChrW(code))
End Function
End Class
C# (DEMO)
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
String sample = "M'arta";
Regex reg = new Regex(#"&#(\d{1,3});");
Console.WriteLine(reg.Replace(sample, new MatchEvaluator(ReplaceASCIICode)));
}
public static String ReplaceASCIICode(Match m)
{
Int32 code = Int32.Parse(m.Groups[1].Value);
return Convert.ToString((char)code);
}
}
You can parse the string looking for the #digits and then put the found code through the ChrW .NET function.
If you don't know regex then something like this
Dim idx As Integer = occupant.IndexOf("#")
If idx <> -1 Then
idx += 1
Do While idx < occupant.Length
If IsNumeric(occupant(idx)) Then
s &= occupant(idx)
Else
Exit Do
End If
idx += 1
Loop
If s.Length > 0 Then
s = Convert.ToChar(CInt(s))
End If
Stop
End If
It would need slight modification to handle multiple instances of #.
I don't know VB.NET, but here is a C# solution. I am pretty sure you can handle the conversion to Visual Basic.
using System;
using System.Text.RegularExpressions;
class Program {
static void Main(string[] args) {
String input = "M#39arta";
String output = Regex.Replace(input, #"#\d\d", Replace);
Console.WriteLine(output);
Console.ReadLine();
}
static String Replace(Match match) {
int charCode = int.Parse(match.Value.Substring(1));
return ""+ (char)charCode;
}
}

Iterate through Custom Object's Property Names and Values

I'm trying to create an export Excel/CSV function that will iterate through a custom object and first output the property names and then output the values. I want to use reflection only where necessary so I'm attempting to save the property names when I output the headers and then reuse them to print the values.
Is this possible? I'm a little weary of using reflection in a loop but is there a better way?
Psuedo Code:
Dim Cust1 = New Customer("Tom", "123 Main Street")
Dim Cust2 = New Customer("Mike", "456 Main Street")
Dim Cust3 = New Customer("Joe", "789 Main Street")
Dim CustList As New Arraylist()
CustList.Add(Cust1)
CustList.Add(Cust2)
CustList.Add(Cust3)
CSVExport(CustList, New Customer())
Function CSVExport(List As ArrayList, CustomObject as Object) As StringWriter
Dim sw as Stringwriter
dim proplist as arraylist
'output header
Foreach CustProperty as System.Reflection.PropertyInfo CustomObject.GetType().GetProperties()
proplist.add(CustProperty.Name)
sw.write(CustProperty + ",")
EndFor
'output body
'??
'?? Here I'd like to loop through PropList and List instead of using reflection
'??
Return Sw
End Function
Its all reflection regardless of whether or not you have the names stored in a list.
Do you have a degree of control over the CustomObject. You could store the info within the CustomObject and query that info instead without using reflection. For instance, this is the code I use for my basic domain objects.
public class DomainObject
{
private HashTable _values = new HashTable();
public HashTable Properties
{
get
{
return _values;
}
}
protected void SetValue<T>(string property, T value)
{
if (_values.ContainsKey(property))
{
_values[property] = value;
}
else
{
_values.Add(property, value);
}
}
protected T GetValue<T>(string property)
{
if (_values.ContainsKey(property))
{
return (T)_values[property];
}
else
{
return default(T);
}
}
}
public class TootsieRoll : DomainObject
{
public string Size
{
get { return GetValue<string>("Size"); }
set { SetValue<string>("Size",value); }
}
public string Flavor
{
get { return GetValue<string>("Flavor"); }
set { SetVlaue<string>("Flavor", value); }
}
public int Ounces
{
get { return GetValue<int>("Ounces"); }
set { SetValue<int>("Ounces", value); }
}
}
Now your CSV code would only need to access and loop through the Key=>Value pairs within the "Properties" HashTable it inherited from the DomainObject to get the names and values. But obviously this only works if you have a level of control over your objects necessry to make them inherit from the DomainObject, and it wouldnt involve 30 years of drugery to rewrite all your property accessors. If that is the case, then reflection is your way to go.
In your Pseudo Code you're already populating an arraylist using reflection. If all you want to do is loop through the ArrayList, you can have a look at the ArrayList Class MSDN entry. It shows how to implement IEnumerable to iterate your array list, e.g:
Dim obj As [Object]
For Each obj In CType(myList, IENumberable)
Console.Write(" : {0}", obj)
Next obj
That's untested as is, I'm not sure if it should be CType(myList, IENumberable) or DirectCast(myList, IENumberable).
There is another option, using Object Serialization in VB.Net, a road far less traveled (at least around our offices).

Declare return Type of the Function when there are two possible returned types

I have the following statement, I want to turn it into a Public Shared Function :
If isEmployee Then
Dim employeeInstance As New Employee
employeeInstance = GetEmployeeInstanceByUserId(userId)
Return employeeInstance
Else
Dim studentInstance As New Student
studentInstance = GetStudentInstanceByUserId(userId)
Return studentInstance
End If
Public Shared Function GetWorkerInstance(Byval isEmployee as Boolean) As ...(not sure what to write here)...
There two possible return Type. I'm not sure what I should declare for the function return type.
Any suggestion? Thank you.
This would be easiest if both the Employee and Student classes derived from one parent (either a base class or interface), then you could use that as your return type.
You can't declare different return types on the one function and you will not be able to create overrides that return different types, as the method signature resolution does not consider return types.
Generic
Private Class foo
Dim s As String = "FOO"
End Class
Private Class bar
Dim s As String = "BAR"
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim o As Object = GetWorkerInstance(True)
If TypeOf o Is foo Then
Stop
Else
Stop
End If
End Sub
Public Shared Function GetWorkerInstance(ByVal isEmployee As Boolean) As Object
If isEmployee Then Return New foo Else Return New bar
End Function

Resources