ina c# project i have a static async task written to send emails via tmpt-relay.
the main function is calling this task.
This is working fine.
My Problem is i'm calling this function from a vb.net project, this is also working, email was send but vb.net is hanging in the c#-call
My Code in c#
public class SmoffMail
{
public static string sRet;
public string sendMail(string mailto)
{
RunAsync(mailto).Wait();
return sRet;
}
static async Task RunAsync(string mailto){
MailjetClient client = new MailjetClient("419cce0b9807d1016642156966fc4ec1",
....
sRet = "ok.....";
}
}
From the vb.net i call it like this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim smail As New smoff.Mailjet.SmoffMail
Dim i As Integer = 0
Dim sRet As String = ""
sRet = smail.sendMail("xxxxxxxh#bluewin.ch")
MsgBox(sRet)
End Sub
End Class
So the function smail.sendMail() was called but is hanging, the next line in code ( msgbox ) is nerver attempt.
Thanks for your help
Your C# should look like this:
public class SmoffMail
{
static async Task<string> SendMailAsync(string mailto){
MailjetClient client = new MailjetClient("419cce0b9807d1016642156966fc4ec1",
....
return "ok.....";
}
}
And your VB should look like this:
Public Class Form1
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sRet As String = ""
sRet = Await smoff.Mailjet.SmoffMail.SendMailAsync("xxxxxxxh#bluewin.ch")
MsgBox(sRet)
End Sub
End Class
Let your VB go back to drawing the UI while it waits for your 2 gigabyte attachment to upload, otherwise there's no point in having any of this be async
i found the solution, the problem was not my code, it was the API Mailjet.client.
after changing the call to this API it works fine
Related
to create functionallity in my project I need to convert this C# sample to vb.net
I can only connect (Read/Write) to the backend using this API.
to get the details of a customer from a database:
Customer.BeginFetch(CustomerId, AfterFetchingCustomer);
private void AfterFetchingCustomer(object sender, DataPortalResult<Customer> dataPortalResult)
{
Invoke((Action)(() =>
{
_customer = dataPortalResult.Object;
txtShortName.Text = _customer.ShortName;
}));
}
//This is from the API in C#
public static void BeginFetch(string customerId, EventHandler<DataPortalResult<Customer>> callback, AdministrationContext context = null);
I tried:
Dim Debb Debiteur.CustomerId = "DE16000"
Customer.BeginFetch(Debiteur, AfterFetchingCustomer)
End Sub
Private Sub AfterFetchingCustomer(sender As Object, e As DataPortalResult(Of Customer))
End Sub
''This is from the API in VB:
Public Shared Sub BeginFetch(customerId As String, callback As EventHandler(Of DataPortalResult(Of Customer)), Optional context As AdministrationContext = Nothing)
But still get the errors:
Argument not specified for parameter sender ...
Argument not specified for parameter e ...
How can i get this code validated?
So I can continue to work on this program.
Thanks in advance!
When i am performing large imports from data to put into sql using entity framework, my code has to check the same foreign keys that results in repetitive commands to the sql server. I believe i need to use 2nd level cache, i have tried to use the efcache from nuget, but as i am only used to vb.net, i am having trouble converting the following c# code:
public class Configuration : DbConfiguration
{
public Configuration()
{
var transactionHandler = new CacheTransactionHandler(new InMemoryCache());
AddInterceptor(transactionHandler);
Loaded +=
(sender, args) => args.ReplaceService<DbProviderServices>(
(s, _) => new CachingProviderServices(s, transactionHandler,
new DefaultCachingPolicy()));
}
}
to vb
Imports System.Data.Entity
Imports EFCache
Public Class Configuration
Inherits DbConfiguration
Public Sub New()
Dim transactionHandler = New CacheTransactionHandler(New InMemoryCache())
AddInterceptor(transactionHandler)
AddHandler Loaded, Function(sender, args) args.ReplaceService(Of
DbProviderServices)(Function(s, _) New CachingProviderServices(s,
transactionHandler, New DefaultCachingPolicy()))
End Sub
End Class
I understand that i need to change c# += to addhandler, but it doesnt recognise dbproviderservices, the underscore _ and DefaultCachingPolicy.
You are using incorrect method signatures.
DbConfiguration.Loaded
Public Shared Event Loaded As EventHandler(Of DbConfigurationLoadedEventArgs)
DbConfigurationLoadedEventArgs.ReplaceService(Of TService)
Public Sub ReplaceService(Of TService) (serviceInterceptor As Func(Of TService, Object, TService))
So the code should look more like this:
AddHandler Loaded,
Sub(sender As Object, e As DbConfigurationLoadedEventArgs)
e.ReplaceService(Of DbProviderServices)(
Function(serviceInterceptor As DbProviderServices, o As Object)
Return New CachingProviderServices(serviceInterceptor, transactionHandler, New DefaultCachingPolicy())
End Function)
End Sub
Compact version:
AddHandler Loaded, Sub(sender As Object, e As DbConfigurationLoadedEventArgs) e.ReplaceService(Of DbProviderServices)(Function(serviceInterceptor As DbProviderServices, o As Object) New CachingProviderServices(serviceInterceptor, transactionHandler, New DefaultCachingPolicy()))
This question already has answers here:
VB.NET equivalent to C# var keyword [duplicate]
(4 answers)
Closed 8 years ago.
I'm looking at trying to implement a mediator helper class to facilitate the transfer of information between viewmodels.
Starting with the following in c#
static public class Mediator
{
static IDictionary<string, List<Action<object>>> pl_dict = new Dictionary<string, List<Action<object>>>();
static public void Register(string token, Action<object> callback)
{
if (!pl_dict.ContainsKey(token))
{
var list = new List<Action<object>>();
list.Add(callback);
pl_dict.Add(token, list);
}
else
{
bool found = false;
foreach (var item in pl_dict[token])
if (item.Method.ToString() == callback.Method.ToString())
found = true;
if (!found)
pl_dict[token].Add(callback);
}
}
static public void Unregister(string token, Action<object> callback)
{
if (pl_dict.ContainsKey(token))
pl_dict[token].Remove(callback);
}
static public void NotifyColleagues(string token, object args)
{
if (pl_dict.ContainsKey(token))
foreach (var callback in pl_dict[token])
callback(args);
}
}
I end up with the following in vb (courtesy of telerik's online converter
Public NotInheritable Class Mediator
Private Sub New()
End Sub
Shared pl_dict As IDictionary(Of String, List(Of Action(Of Object))) = New Dictionary(Of String, List(Of Action(Of Object)))()
Public Shared Sub Register(token As String, callback As Action(Of Object))
If Not pl_dict.ContainsKey(token) Then
Dim list = New List(Of Action(Of Object))()
list.Add(callback)
pl_dict.Add(token, list)
Else
Dim found As Boolean = False
For Each item As var In pl_dict(token)
If item.Method.ToString() = callback.Method.ToString() Then
found = True
End If
Next
If Not found Then
pl_dict(token).Add(callback)
End If
End If
End Sub
Public Shared Sub Unregister(token As String, callback As Action(Of Object))
If pl_dict.ContainsKey(token) Then
pl_dict(token).Remove(callback)
End If
End Sub
Public Shared Sub NotifyColleagues(token As String, args As Object)
If pl_dict.ContainsKey(token) Then
For Each callback As var In pl_dict(token)
callback(args)
Next
End If
End Sub
End Class
The compiler doesn't like the two For Each <...> As var statements. I'm assuming that this is linq c# style which has always been very difficult to translate with ease. This one has me ostensibly because I'm still trying to fathom out the whole principle anyway. Can anyone suggest a proper construct for the two lines in question.
Thanks
In VB, the equivalent of var is to simply declare the variable without specifying the type, for instance:
For Each callback In pl_dict(token)
callback(args)
Next
However, in order for that to work, you need to have Option Infer On. Alternatively, you could just specify the type of the iterator variable as whatever it actually is (in this case, Action(Of Object)), like this:
For Each callback As Action(Of Object) In pl_dict(token)
callback(args)
Next
Using VS 2010, VB.NET, HTTPClient, .NET 4.0, and Windows Forms.
I am trying to get a windows application to consume JSON coming from a Web API that I have created. Web API works great and I can view the results from a browser. Found this article that I have been trying to get working only using VB.NET instead of C#.
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-wpf-application
The critical part of the code is this function:
private void GetProducts(object sender, RoutedEventArgs e)
{
btnGetProducts.IsEnabled = false;
client.GetAsync("api/products/2").ContinueWith((t) =>
{
if (t.IsFaulted)
{
MessageBox.Show(t.Exception.Message);
btnGetProducts.IsEnabled = true;
}
else
{
var response = t.Result;
if (response.IsSuccessStatusCode)
{
response.Content.ReadAsAsync<IEnumerable<Product>>().
ContinueWith(t2 =>
{
if (t2.IsFaulted)
{
MessageBox.Show(t2.Exception.Message);
btnGetProducts.IsEnabled = true;
}
else
{
var products = t2.Result;
_products.CopyFrom(products);
btnGetProducts.IsEnabled = true;
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
I have tried to convert this to VB.NET but I am having issues with the t.Result saying "'Result' is not a member of 'System.Threading.Tasks.Task'."
Here is my attempt to convert it to VB.NET:
Private Sub GetProducts(sender As Object, e As RoutedEventArgs)
btnGetProducts.IsEnabled = False
client.GetAsync("api/products/2") _
.ContinueWith(Of HttpResponseMessage) _
(Function(t)
If t.IsFaulted Then
MessageBox.Show(t.Exception.Message)
btnGetProducts.IsEnabled = True
Else
'***************************************************************
Dim response = t.Result 'This is the line that is giving me grief. Error Msg: 'Result' is not a member of 'System.Threading.Tasks.Task'.
'***************************************************************
If response.IsSuccessStatusCode Then
response.Content.ReadAsAsync(Of IEnumerable(Of SendNotice)).ContinueWith _
(Function(t2)
If t2.IsFaulted Then
MessageBox.Show(t2.Exception.Message)
btnGetProducts.IsEnabled = True
Else
Dim products = t2.Result
_lstSN.CopyFrom(products)
btnGetProducts.IsEnabled = True
End If
End Function, TaskScheduler.FromCurrentSynchronizationContext())
End If
End If
End Function, TaskScheduler.FromCurrentSynchronizationContext())
End Sub
Any idea why I am getting this error and what am I missing in my code to allow me to catch the returning JSON data?
Thanks!
This is because VB.NET type inference is not great in Visual Studio 2010. You'll need to give the compiler a bit of extra help by specifying the actual type returned by your client.GetAsync(), like so:
client _
.GetAsync("api/products/2") _
.ContinueWith( _
Sub(t As Task(Of HttpResponseMessage))
...
End Sub, _
TaskScheduler.FromCurrentSynchronizationContext())
Note: I've changed your Function to Sub because I didn't see any Return statements.
Try this:
client.GetAsync("api/products/2") _
.ContinueWith(Sub(t)
If t.IsFaulted Then
.
.
.
Try changing your lambda from a Function to a Sub.
StackTrace: at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
Source: mscorlib
I see in the target source something about reflection. So i'll post the very small amount of code that uses reflection.
I normally am able to find NullReferenceExceptions easily. This one though does not appear to be my code, and I can not figure it out to save my life. I have this code bot in VB.net, and C#.Net Both have the same problem. I think that my problem is in how my pointer works, but I could be wrong.
The code is straight forward. I have a barcode scanner attached via usb that is in COM mode. I copied some of my code from another program that uses this same barcode that works perfectly. But to sum up what it does is that it opens, then, by use of reflection, gets the Pointer to the open com port, sets up a DataEventListener. When I scan something i wait 100ms, then spit out the data in string form. Simple as could be. The difference between my code and the other one that works flawlesly is that I have to get the pointer. To turn on my scanner i need a pointer to the comport using IntPtr. C# I use IntPtr, in VB i use SafeFileHandle. Both have the same error. The only time the error occurs is when a data event is fired. This is why I think it has to be with the handle. What is strange is that the Handle is needed to turn on and off the imager so I know i have a valid handle. (just don't know if it is held on to) So does anyone have any help or resources as to why I am having this error?
First up.. VB.NET
Public Class ImagerOposDevice
Inherits AbstractOPOSDevice
Dim PortHandle As SafeFileHandle
Dim ImagerPort As SerialPort
Public exitCode = 1
Sub New(ByVal comName As String)
ImagerPort = New SerialPort(comName)
End Sub
Protected Overrides Function Open() As Boolean
ImagerPort.Open()
PortHandle = GetHandleFromSerialPort(ImagerPort)
If Not PortHandle.IsInvalid Then
AddHandler ImagerPort.DataReceived, AddressOf DataReceivedHandler
End If
Return (Not PortHandle.IsInvalid)
End Function
Protected Overrides Sub Close()
Try
ImagerPort.Close()
ImagerPort.Dispose()
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.ReadLine()
End Try
End Sub
Protected Overrides Function RunCommand(ByVal X As Integer) As Boolean
If X = 0 Then
Return TurnImagerOn()
ElseIf X = 1 Then
Return TurnImagerOff()
Else
Return False
End If
End Function
Private Shared Function GetHandleFromSerialPort(ByVal sp As SerialPort) As SafeFileHandle
Dim BaseStream As Object = sp.BaseStream
Dim BaseStreamType As Type = BaseStream.GetType
Return BaseStreamType.GetField("_handle", BindingFlags.NonPublic Or BindingFlags.Instance).GetValue(BaseStream)
End Function
Private Sub DataReceivedHandler(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
Try
'Dim sp As SerialPort = CType(sender, SerialPort)
System.Threading.Thread.Sleep(100)
Dim len = ImagerPort.BytesToRead
Dim buffer(len - 1) As Byte
ImagerPort.Read(buffer, 0, len)
Dim indata As String = System.Text.ASCIIEncoding.ASCII.GetString(buffer)
Console.WriteLine("Data Received:")
Console.Write(indata)
TurnImagerOff()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
exitCode = 0
End Sub
in my main form it is straight forward
imager = New ImagerOposDevice("COM7")
imager.OpenDevice()
imager.SendCommand(0)
For index = 1 To 100 Step 1
System.Threading.Thread.Sleep(100)
If imager.exitCode = 0 Then
Exit For
End If
Next
Console.WriteLine("Press Enter to Close")
Console.ReadLine()
CloseDevices()
Now for the C# code. It is a windows form, but the concept is almost identicle.
private SerialPort devicePort;
private IntPtr deviceHandle;
public Imager(string Port) : base()
{
devicePort = new SerialPort(Port);
}
protected override bool Open()
{
try
{
devicePort.Open();
deviceHandle = GetHandleFromSerialPort(devicePort);
Console.WriteLine("Device Handle:{0}", deviceHandle);
Console.WriteLine("Device Open:{0}", devicePort.IsOpen);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
return devicePort.IsOpen;
}
protected override bool Close()
{
devicePort.Close();
devicePort.Dispose();
return true;
}
protected override CommandReturnCodes RunCommand(int command)
{
switch (command)
{
case 0:
TurnImagerOn();
break;
case 1:
TurnImagerOff();
break;
case 2:
ReadLatch();
break;
case 3:
GetPartNumber();
break;
case 4:
GetSerialNumber();
break;
case 5:
GetProductString();
break;
default:
return CommandReturnCodes.FAIL;
}
return CommandReturnCodes.SUCCESS;
}
private static IntPtr GetHandleFromSerialPort(SerialPort sp)
{
Type t = typeof(SerialPort);
BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic;
FieldInfo fi = t.GetField("internalSerialStream", bf);
object ss = fi.GetValue(sp);
Type t2 = fi.FieldType;
FieldInfo fi2 = t2.GetField("_handle", bf);
SafeFileHandle _handle = (SafeFileHandle)fi2.GetValue(ss);
Type t3 = typeof(SafeFileHandle);
FieldInfo fi3 = t3.GetField("handle", bf);
IntPtr handle = (IntPtr)fi3.GetValue(_handle);
return handle;
}
public void TurnOnImagerEventListener()
{
devicePort.DataReceived += new SerialDataReceivedEventHandler(devicePort_DataReceived);
}
void devicePort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(100);
SerialPort imager = sender as SerialPort;
byte[] buffer = new byte[imager.BytesToRead];
imager.Read(buffer, 0, imager.BytesToRead);
var scannedText = System.Text.Encoding.ASCII.GetString(buffer).Trim();
SendBarcodeEvent(scannedText);
TurnImagerOff();
Console.WriteLine(scannedText);
}
and to call it is same thing
im = new Imager(comportBox.Text);
im.OpenDevice();
im.TurnOnImagerEventListener();
im.BarcodeScanned += new DataAvailableHandler(DeviceInformationReceived);
Well it turns out that LightStriker helped me see past this fog that was blinding me yesterday. I still don't have the vb.net version working, but what it ended up being was that the IntPtr used in my C# program was not being retained when a seperate thread (IE the dataevent) called it. When I stepped through the data event portion it didn't fail until i called the TurnImagerOff() portion. It was a easy fix in that all i had to do was change both my serial port and my IntPtr into static Members. I tried that in the VB.net code...but evidently I'm not smart enough to figure that out. Oh well today is another day, and atleast 50% of my code works.
So for those of you who have a null reference error and can't find it any where. And the Stack Trace doesn't give you a line number, check anything that is running on another thread that is making a call to any members that are pointers. (Or reflected as a pointer). Check data events, Thread Pools, Background workers, Timers, delegates, etc. I hope that my follies will help someone else.