I'm trying to convert a sub to be async and, according to every documentation (and as far as I can remember, I did it in the past), it says that I should convert my sub to a Function() as Task.
My problem is that as soon as I hit enter, it is modified to Function() as Task(of Task). To make sure it was not something inside my method, I did an empty one but it resulted in the same behaviour. I also tried doing ctrl+z to force to keep as Task but then I get, on the method,
BC36945 Visual Basic AND VB.NET The 'Async' modifier can only be used on Subs, or on Functions that return Task or Task#Of T#.
and on the caller,
BC36930 Visual Basic AND VB.NET 'Await' requires that the type 'Task' have a suitable GetAwaiter method.
Is it normal? Is it a new behaviour in 4.6.1? Or is there something additional I should do to have it work as expected and return void?
Note: I'm on Framework 4.6.1 with TupleValue nuget installed.
As mentionned by #HansPassant, for Task to be used directly without its full namespace (System.Threading.Tasks.Task), the correct import must be present (which is generally the case by default) and no other namespace should collide with it.
In my specific case, I had Microsoft.Exchange.WebServices.Dataimported which also contains a Task type so when VS modified my signature for async with as Task(of Task), what was really there was as System.Threading.Tasks.Task(Of Microsoft.Exchange.WebServices.Data.Task).
In my project, I fixed the ambiguity by adding Imports Tsk = System.Threading.Tasksand then I was able to simply write as Tsk.Task.
Related
I have created a function called test that returns a boolean in a separate js file and I could call this function inside and aspx.vb file in vb.net as such:
ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "test();", True)
my question is how to capture this returned value and assign it to a variable in vb.net so I can use it in a vb conditional statement?
Actually you aren't calling the function. What RegisterStartupScript does is that it "tells" to the browser that it should run the test() function as soon as it's ready to do so.
With that been said, you cannot get a return value from the test() function because when it gets called your aspx vb code has already been executed. Take a look here for more information regarding the life cycle of an aspx page.
Usually it is not a good idea to write server side code (aspx) that depends on the result of client side code (js), however what you can do is to have the test() js function to do an ajax request in the aspx page and "go on" from there. Here is a small example. The thing is that this approach isn't suitable nor it's recommended for what, I suspect, you are trying to do. To present different web page parts to the user according to the output of the test() js function.
I cannot provide sample code for what I suggest because it will be a wrong use case. I am answering this just to emphasize that you actually can't do what are you asking and even if there is a way to do it you should definitely avoid it. However, this is a good opportunity to dive in more in the web applications design and implementation.
Perhaps an SPA can fit your needs?
What I want:
get a xml from the AppData to use
What I code
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile sampleFile = localFolder.GetFileAsync("abc.xml");
What I get
Error: Cannot implicitly convert type 'Windows.Foundation.IAsyncOperation' to 'Windows.Storage.StorageFile'
What I Check
When this method completes successfully, it returns a StorageFile that
represents the file.
from MSDN
What I have
Windows 8 Release Preview 64bit;
Visual Studio Express 2012 RC for Windows 8;
C#
I write the code according to the MSDN doc, Why does this error happen and how to resolve it?
Larry gave you the right solution. Let me try to explain what was going on.
If you look at the MSDN documentation for GetFileAsync, you will see that it returns an IAsyncOperation. Your code assumes that it returns a SampleFile. GetFileAsync doesn't provide a file, it provides an object which will provide a file once the retrival is complete.
Await in C# provides a function that will be called by that object (or on behalf of that object) once the conditions for completion are satisfied. That function then returns the value to you. A promise in JavaScript (.then or .done) provides similar functionality, but you have to supply the function yourself.
The reason for this is so that the application can be responsive. File access is slow. If accessing memory took 1 second, then file access would take about 15 minutes. Asynchronous programming allows other things to happen while your program is waiting.
Try using "StorageFile sampleFile = await localFolder.GetFileAsync("abc.xml")" if you're in C# or "localFolder.GetFileAsnc("abc.xml").done(function (sampleFile) {})" if you're using JS.
My company's main software package includes a hefty configuration library which loads on startup. This config library includes some mandatory settings which, if not supplied (via command line arguments), cause the entire application to exit.
This has never been an issue for our users, who launch the software via scripts which have the needed command line arguments supplied automatically. But sometimes when debugging our software we developers forget to specify the necessary arguments in Visual Studio's debug options; it's then very annoying to be greeted with the message Config specification invalid -- missing required parameters X, Y, and Z -- shutting down (I'm paraphrasing, of course).
It's not really a big deal, just an annoyance. Still, I felt it worthwhile to throw together a little form to make this process a little less painful; it notifies the user which parameters are missing and allows him/her to specify values for those parameters directly on the form, without having to restart the application.
My intentions were good (I think?), but it seems I can't get this solution to actually work. The problem is that after I've launched our software with missing settings, the form pops up and prompts me as expected; but after I've entered the required parameters and it's time for the application to "really" start, I get this InvalidOperationException:
SetCompatibleTextRenderingDefault must
be called before the first
IWin32Window object is created in the
application.
I think I understand what's going on here: the VB.NET project I'm working on is doing something like this "behind the scenes"*:
Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New MainForm)
End Sub
That call to SetCompatibleTextRenderingDefault is, apparently, throwing an exception because a form was already created and displayed prior to its execution.
Is there any way around this? Is there perhaps a more "proper" solution to this problem that I'm not thinking of (i.e., should I not be trying to collect user input via a form at all)?
*This is a best guess based on what I've seen in C# WinForms projects. Strangely, unless I'm missing something, it seems that VB.NET WinForms projects completely hide this from the developer.
Do make sure that you have the application framework option turned off and Sub Main selected as the starting method. Make it look similar to this:
Sub Main(ByVal args() As String)
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
If args.Length = 0 Then
Using dlg As New OptionsDialog
If dlg.ShowDialog <> DialogResult.OK Then Return
'' Use dlg result...
End Using
End If
Application.Run(New MainForm)
End Sub
Perhaps you could use the static Debugger.IsAttached (or even a #DEBUG directive) in your program's "main" function that feeds in some input file (say an XML file) into your parsed args collection instead?
I am working on a VB.NET batch PDF exporting program for CAD drawings. The programs runs fine, but the architecture is a mess. Basically, one big function takes the entire process from start to finish. I would like to make a separate class, or several, to do the exporting work.
Here's the problem:
Sometimes the pdf file which will be created by my program already exists. In this case, I would like to ask the user if he/she would like to overwrite existing PDFs. I only want to do this if there is actually something which will be overwritten and I only want to do this once. In other words, "yes" = "yes to all." It seems wrong to have the form (which will be calling this new PDF exporting class) figure out what the PDF files will be called and whether there will be any overwrites. In fact, it would be best to have the names for the PDF files determined as the individual CAD drawings are processed (because I might want to use information which will only become available after loading the files in the CAD program in the background).
Here's the question:
How should I handle the process of prompting the user? I would like to keep all GUI logic (even something as simple as a dialog box) out of my PDF exporting class. I need a way for the PDF exporting class to say, "Hey, I need to know if I should overwrite or skip this file," and the form class (or any other class) to say, "Um, ok, I'll ask the user and get back to you."
It seems there ought to be some pattern to handle this situation. What is it?
Follow-ups:
Events: It seems like this is a good way to go. Is this about what the code should look like in the PDF exporting class?
Dim e As New FileExistsEventArgs(PDFFile)
RaiseEvent FileExists(Me, e)
If e.Overwrite Then
'Do stuff here
End If
A crazy idea: What about passing delegate functions to the export method of the PDF exporting class to handle the overwrite case?
You could use an Event, create a custom event argument class with a property on it that the application can call. Then when your app is handling the event prompt the user and then tell the exporter what to do. I'm a c# guy so let me give you a sample in there first:
void form_Load(object sender,EventArgs e)
{
//We are subscribing to the event here. In VB this is done differently
pdfExporter.FileExists+=new FileExistsEventHandler(pdfExporter_fileExists)
}
void pdfExporter_fileExists(object sender, FileExistsEventArgs e)
{
//prompUser takes the file and asks the user
if (promptUser(e.FileName))
{
}
}
Your PDF making class should raise an event. This event should have an eventargs object, which can have a boolean property called "Overwrite" which the GUI sets in whatever fashion you want. When the event returns in your PDF class you'll have the user's decision and can overwrite or not as needed. The Gui can handle the event anyway it likes.
Also, I commend you for working to keep the two seperate!
So the appropriate method on your class needs an optional parameter of
[OverwriteExisting as Boolean = False]
However your form will need to handle the logic of establishing whether or not a file exists. It seems to me that this would not be a function that you would want encapsulated within your PDF export class anyway. Assuming that your form or other function/class ascertains that an overwrite is required then the export methos is called passing True as a Boolean to your export class.
You could do a two phase commit type of thing.
The class has two interfaces, one for prepping the filenames and filesystem, and another for doing the actual work.
So the first phase, the GUI calls the initialization interface, and gets a quick answer as to whether or not anything needs over-writing. Possibly even a comprehensive list of the files that will get over-written. User answers, the boolean variable in the other responses is known, and then the exporter gets to the real work, and the user can go do something else.
There would be some duplication of computation, but it's probably worth it to get the user's part of the operation over with as soon as possible.
You can't keep the GUI stuff out of the PDF Exporting Code. but you can precisely define the minimum needed and not be tied to whatever framework you are using.
How I do it is that I have a Status class, and a Progress class. The two exist because Status is design to update a status message, and the Progress Bar is designed to work with a indicator of progress.
Both of them work with a object that has a class type of IStatusDisplay and IPrograssDisplay respectfully.
My GUI defines a object implementing IStatusDisplay (or IProgressDisplay) and registers as the current display with the DLL having Status and Progress. The DLL with Status and Progress also have two singleton called NullStatus and NullProgress that can be used when there is no UI feedback wanted.
With this scheme I can pepper my code with as many Status or Progress updates I want and I only worry about the implementations at the GUI Layer. If I want a silent process I can just use the Null objects. Also if I completely change my GUI Framework all the new GUI has to do is make the new object that implements the IStatusDisplay, IProgressDisplay.
A alternative is to raise events but I find that confusing and complicated to handle at the GUI level. Especially if you have multiple screen the user could switch between. By using a Interface you make the connection clearer and more maintainable in the longe.
EDIT
You can create a Prompt Class and a IPromptDisplay to handle situation like asking whether you want to overwrite files.
For example
Dim P as New Prompt(MyPromptDisplay,PromptEnum.YesNo)
'MyPromptDisplay is of IPromptDisplay and was registered by the GUI when the application was initialized
If PromptYesNo.Ask("Do you wish to overwrite files")= PromptReply.Yes Then
'Do stuff here
End If
We have a web service solution in VB .Net 2005 that we have started getting an error in. We provide an interface like the following:
Public Interface IBatchTrackerService
Function InsertBatchTracker(ByVal BatchTrackerObject As BatchTracker, ByRef errorNum As Integer, ByRef errorMsg As String) As Integer
End Interface
In our class we implement this interface with the following code.
Public Class BatchTrackerService
Implements IBatchTrackerService
Public Function InsertBatchTracker(ByVal BatchTrackerObject As BusinessObjects.BatchTracker, ByRef errorNum As Integer, ByRef errorMsg As String) As Integer Implements IBatchTrackerService.InsertBatchTracker
'Some code here'
End Function
End Class
This code was working properly but has now started causing errors. The error we receive is:
Class 'BatchTrackerService' must implement 'Function InsertBatchTracker(BatchTrackerObject As BusinessObjects.BatchTracker, ByRef errorNum As Integer, ByRef errorMsg As String) As Integer' for interface 'IBatchTrackerService'.
The odd thing is that the project compiles correctly, but shows many of these errors after the compile is finished.
We recently installed Panda as our virus protection which caused a different error that I found the solution here for.
Any help would be greatly appreciated.
Thank you.
Updated 4/21/2009 at 11:50
Both the interface and the implementation are within the same project in the solution.
Updated 4/22/2009 at 08:16
I tried removing the BusinessObjects identifier from in front of the BatchTracker type but I still get the same thing. This is just one example of what has happened throughout the entire solution. Every implementation in this BatchTrackerService is flagged as an error, plus there are several other services that have almost every implementation flagged as an error as well. But somehow the project builds successfully, and yes, it runs properly!
As for BusinessObjects, it contains many of the classes we use as parameters and it is simply another project within this solution. We do not reference any external assemblies to provide these classes to BusinessObjects.
Updated 4/22/2009 at 08:24
The last thing I noticed was that any function/procedure that doesn't use a 'BusinessObjects' class as a parameter, but simply uses strings, integers, etc is not flagged as an error.
Updated 4/22/2009 at 09:50
I tried reverting back to a previous version and I was able to compile and the error count stayed at zero. I narrowed it down to a check-in of one of the project files where the reference to BusinessObjects was slightly changed. I reverted just this project file and everything compiles fine now. Thanks to everyone for leading me in the right direction.
It sounds like you're loading up a different version of the assembly that contains your interface in the web service and in the client, causing the client to reject the signature implemented by the web interface. Ensure that the versions are the same and, if necessary, strong-sign the assembly.
Your interface specifies that the "BatchTrackerObject" parameter be of type "BatchTracker" but your implementation uses type "BusinessObjects.BatchTracker". Try removing the "BusinessObjects." qualifier from your implementation.
Do multiple assemblies provide classes within the BusinessObjects namespace?