In a UWP C# app, need background (ie. worker) thread to use UI thread to display an image. But can't figure out how to compile Dispatcher.RunAsync().
using Foundation;
using System;
using UIKit;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using System.Threading;
using System.Windows.Threading; <<<<<<<<<< gets error
using Windows.UI.Core; <<<<<<<<<< gets error
public async static void process_frame()
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// "the name dispatcher does not exist in current context"
//UI code here:
display_frame();
});
}
public void display_frame()
{
var data = NSData.FromArray(System_Hub_Socket.packet_frame_state.buffer);
UIImageView_camera_frame.Image = UIImage.LoadFromData(data);
}
Latest method
public async static void process_frame( /* ax obsolete: byte[] camera_frame_buffer, int frame_size_bytes */ )
{
await Task.Run( () => { viewcontroller.display_frame(); } );
}
// [3]
// Copies latest frame from camera to UIImageView on iPad.
// UI THREAD
public Task display_frame()
{
var data = NSData.FromArray ( System_Hub_Socket.packet_frame_state.buffer);
<<<<<< ERROR
UIImageView_camera_frame.Image = UIImage.LoadFromData( data );
return null;
}
Error from the latest method
Looking at the using statements in you code:
using UIKit;
...
using Windows.UI.Core;
This just can't happen. UIKit is a Xamarin.iOS, platform-specific namespace and Windows.UI.Core is Windows platform-specific namespace and in no way can those two be mixed in one file (except for shared project with #if directives that is, but that is not the case here).
Xamarin helps writing cross-platform apps, but you still cannot use platform specific APIs on OS on which they are not available. Windows has Dispatcher as a means of running code on the UI thread, but this concept is not available on iOS, which uses InvokeOnMainThread method instead.
So if you are writing code that is in the platform-specific iOS project, you must use iOS APIs. If you are writing code that is in the platfrom-specific UWP project, you must use UWP APIs - things like Dispatcher will work without problem there.
Finally, if you are writing code in a .NET Standard library, you cannot write any platform specific code directly and must use dependency injection to define an interface behind which you hide the use of platform specific APIs.
Related
I'm trying to follow this answer https://stackoverflow.com/a/47295752/1237135, in order to get a list of IIS Express websites, which involves referencing Microsoft.Web.dll (this is a .NET assembly, but presumably it uses COM calls) and calling this code
using (var runtimeStatusClient = new RuntimeStatusClient())
{
var workerProcess = runtimeStatusClient.GetWorkerProcess(19464);
//there's more but this is all that is needed for failure
}
It actually works, the code runs and has meaningful data, however a few seconds after it completes I get this error
System.InvalidCastException:
'Unable to cast COM object of type 'System.__ComObject'
to interface type 'Microsoft.Web.RuntimeStatus.IRsca2_WorkerProcess'.
This operation failed because the QueryInterface call on the COM component
for the interface with IID '{B1341209-7F09-4ECD-AE5F-3EE40D921870}' failed
due to the following error: No such interface supported (Exception from
HRESULT: 0x80004002 (E_NOINTERFACE)).'
E_NOINTERFACE is often associated with not using an STAThread model, but I've verified that the thread is STA.
The code works without error in a Console app environment, but not WPF.
The answer above mentions
I looked into RegisteredUrlsInfo (in Microsoft.Web.dll) as well and
found that it's using two COM interfaces,
IRsca2_Core (F90F62AB-EE00-4E4F-8EA6-3805B6B25CDD)
IRsca2_WorkerProcess (B1341209-7F09-4ECD-AE5F-3EE40D921870)
And I saw another answer https://stackoverflow.com/a/1058978/1237135 that talks about
Try adding this to your App.exe.manifest:
iid="{C677308A-AC0F-427D-889A-47E5DC990138}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}" tlbid =
"{PUT-YOUR-TLB-GUID-HERE}" /> Where TLBID can be found from your
Visual Studio generated Native.Namespace.Assembly.Name.manifest,
looking like this:
but I'm unclear if this applies here.
I also wondered if it's DLL Hell but that wouldn't explain why it works from a Console, would it?
EDIT: minimal reproduction.
Create a WPF project (I used 4.6.1 runtime) and in the codebehind for the MainWindow I used
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
using (var runtimeStatusClient = new Microsoft.Web.RuntimeStatus.RuntimeStatusClient())
{
var workerProcess = runtimeStatusClient.GetAllWorkerProcesses();
}
}
}
}
The only hard part is you need to find and reference Microsoft.Web.DLL (which if you have IIS Express on your machine should be in your GAC). You can do a Windows search on your C:\ drive and it will probably be somewhere like C:\Windows\assembly\GAC_MSIL\Microsoft.Web\7.1.0.0__31bf3856ad364e35
Do that and you'll see the problem.
Apparently I made 2 fatal assumptions:
Console Apps use STA. However this isn't true, it seems by default they are MTA. That figures I suppose as desktop apps have to explicitly state STA in the Main method.
To do COM interop you have to use STA. I assumed this because using STA is the go-to solution to E_NOINTERFACE problems on the web. However as I understand it now, some COM can use MTA. It appears for Microsoft.Web.DLL, you need MTA.
So my solution is to create a new thread (which will use MTA by default), eg.
public MainWindow()
{
InitializeComponent();
//Do use ThreadPool instead of this...
Thread thread = new Thread(new ThreadStart(() => { GetWebsites(); }));
thread.Start();
}
void GetWebsites()
{
I have created a WCF service and hosted it in IIS. I can access the WCF service by creating a web reference in my asp.net web forms application. I need to have the WCF web service run a long running method (async). Does anyone have good example code of how to call a WCF asynchronous method from an asp.net web forms application button click method?
I have looked at IAsyncResult, EAP, and TAP...
What currently is the best way to make an asynchronous call to a WCF asynchronous method from a ASP.NET web forms application?
I did now change my code to use a Service Reference instead of a Web reference.
Service ReceiptFooterService (ServiceContract, OperationsContract, DataContract):
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Threading.Tasks;
namespace ReceiptFooterDeploymentService
{
[ServiceContract]
public interface IReceiptFooterService
{
[OperationContract(Name = "GetRegisterPingResults")]
Task<List<PingReply>> GetRegisterPingResults(List<StoreIP> potentialIPs);
}
[DataContract]
public class StoreIP
{
private int _storeNumber;
private string _ipAddress;
[DataMember]
public int StoreNumber
{
get
{
return _storeNumber;
}
set
{
_storeNumber = value;
}
}
[DataMember]
public string IPAddress
{
get
{
return _ipAddress;
}
set
{
_ipAddress = value;
}
}
}
}
ReceiptFooterService class:
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace ReceiptFooterDeploymentService
{
public class ReceiptFooterService : IReceiptFooterService
{
public async Task<List<PingReply>> GetRegisterPingResults(List<StoreIP> potentialIPs)
{
var tasks = potentialIPs.Select(sip => new Ping().SendPingAsync(sip.IPAddress, 1000));
var results = await Task.WhenAll(tasks);
return results.ToList();
}
}
}
ASP.NET web forms client: Only first few lines of the method (for brevity)
private List<StoreDetail> PingStoreAndUpdateStatus(List<StoreDetail> storeDetails)
{
ReceiptFooterService.StoreIP[] potentialIPs = GetStoreRegisterIps(storeDetails).ToArray();
ReceiptFooterService.ReceiptFooterServiceClient client = new ReceiptFooterService.ReceiptFooterServiceClient();
List<PingReply> pingReplies = client.GetRegisterPingResultsAsync(potentialIPs).Result.ToList();
I am attempting to ping approximately 2000 IP addresses asynchronously. I am getting back four results that show success. Although, none of the other PingReply details are showing. I need to know what IP address was pinged.
Should I be awaiting somewhere... is that why it is returning to soon, or is there an error causing it to fail. Any suggestions would be appreciated.
Below, is a QuickWatch of my results:
First, when using WCF why don't you use service reference?
(Web vs Service reference)
Then, when using SOAP client, it automatically generates SOAP WCF client with each method with synchronous and asynchronous variant.
Then you just call this async method
MyServiceClient.DummyMethodAsync(someParameters...)
I found that using a WCF web service for the kind of asynchronous work I needed to do (was not working from in the web service).
I switched to creating a console application that I call with arguments, and then store the results in a database. I then have the web site access the results stored in the database.
The console application context is much more friendly to completing the amount of asynchronous methods that I wanted to run at the same time.
Hello I tried creating a rectangle in a wpf application and I'm recieving this error I tried googling it but it didn't work.
Error:
The calling thread must be STA, because many UI components require this.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace Game
{
class Engine
{
#region Members
private Thread _render;
#endregion
public Engine()
{
_render = new Thread(new ThreadStart(Render));
_render.Start();
}
private void Render()
{
while (true)
{
Rectangle rect = new Rectangle();
}
}
}
}
I think this would fix it:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => this.progressBar.Value = 50));
But doesn't that take away the purpose of using a different thread because then all the rendering would still be done on the main thread.
And another question:
I'm trying to draw rectangles of 1 by 1 and detect collision if they "fall" on each other(a loop sets their x--).
Could I also do this with pixels?
Rendering should always be performed on the main thread. That is a design thing in Windows / Win32.
Thanks to the original design of Win32 (which involves handles to windows, aka hWnd's), the thread calling the painting operation must be the same as the one doing the actual painting.
There is a nice article on MSDN about the Threading model and WPF.
I'm experimenting with Dll rebasing on a small test solution running on .net4 consisting of one small .exe and three small .Dlls. The assembly references have been set up correctly and the program compiles and runs just fine.
The aim of this exercise is to examine how rebasing works so that I can tie it in with ngen and get performance increases in a massive project I'm working on.
I've tried many different methods of rebasing the Dlls and monitored the results using vmmap, the visual studio module debugger window and process explorer; nothing has been successful so far:
I've set the Build->Advanced->DLL Base Address setting to 0x41000000, 0x42000000 and 0x43000000 for Dll1.dll, Dll2.dll and Dll3.dll respectively. These addresses were definitely saved as the preferred base address in each of the Dlls, but for each run the Dlls rebased their images erratically to many different locations in memory.
I've tried using this application. The logs it generate show that the Dlls do indeed have the preferred base address (as selected by me) built in, however at runtime the results are still erratic
I've tried using ngen. This results in the .ni versions of the Dlls being loaded alongside the original Dlls, and all 6 of them having erratic memory locations nowhere near the ones I asked for.
I've tried sticking my images in the GAC. It was heartening to see that only the GAC'd versions of the Dlls were loaded, however their memory locations were still erratic.
I've tried what feels like every combination of the above. No success.
Poking around at runtime using VMMap shows that there is a massive gap of available memory in the address space between 0x10000000 and 0x50000000, so there should be no collisions and no need for Dll rebasing to occur. The Dlls are also very small and the 0x01000000 gap I'm leaving between them is extremely generous, so they shouldn't be colliding with each other.
What am I missing?
My main reference during this exercise has been this article, which is highly informative, but was written in 2006 for .Net2: Has something fundamental changed between then and now?
I seriously doubt it makes much difference, but here's the code I'm using just in case:
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Dll1;
using Dll2;
using Dll3;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Thread.CurrentThread.Name = "Poodle";
Console.ReadLine();
//Thread.Sleep(10000);
Blah();
}
static void Blah()
{
Console.WriteLine(Class2.shrooms(5, 'h'));
Class3.teenAngst();
Class1.Wait();
}
}
}
Class1.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Dll1
{
public static class Class1
{
public static void Wait()
{
Console.ReadLine();
Console.Write(" ");
}
}
}
Class2.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Dll2
{
public static class Class2
{
public static string shrooms(int argc, char argv)
{
return "Ranchdaddyx ";
}
}
}
Class3.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Dll3
{
public static class Class3
{
public static void teenAngst()
{
Console.Write("Belonging ");
}
}
}
It is not necessary to rebase JIT compiled code:
JIT-compiled code does not have a rebasing problem since the addresses
are generated at run time based on where the code is placed in memory.
Also, MSIL is rarely affected by base address misses since MSIL
references are token-based, rather than address-based. Thus when the
JIT compiler is used, the system is resilient to base address
collisions.
.NET assemblies and DLL rebasing
If I want to rebase my DLL's, how do I go about doing it?
http://msdn.microsoft.com/en-us/magazine/cc163610.aspx
http://support.microsoft.com/kb/969305
It turns out that ASLR (Address Space Layout Randomization) is the culprit of my confusions. Apparently you can turn it off, but you're sacrificing safety/making a lot of work for yourself. I consider the whole adventure a failed experiment.
.Net .dll's are a very different beast from their unmanaged equivalents. I honestly didn't think that rebasing was relevant.
Check out this MSDN article. Which, among other things, encourages you to NOT rebase. And gives at least one compelling reason NOT to (it could invalidate the signature of a strongly signed assembly). The article also discusses the potential benefits of NGEN (as does your link):
CLR Inside Out
I am trying to port an engine into C# WP7 silverlight, along with its unit tests. Because it uses http requests, it needs to be asynchronous as dictated by the framework. The Android version of the engine I am porting uses synchronous blocking sockets on a worker thread. It invokes a callback whenever the entire operation is complete (not just the http request).
Question - how can I wrap the callback mechanism so that it does an asynch callback that can be used in an [Asynchronous] unit test?
I want it to do something like this:
using System;
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;
[TestClass]
public class WebRequestsTests : WorkItemTest
{
[TestMethod, Asynchronous]
public void TestWebRequest()
{
var webRequest = WebRequest.CreateHttp("http://www.stackoverflow.com");
webRequest.BeginGetResponse(result =>
{
EnqueueCallback(() =>
{
WebResponse response = webRequest.EndGetResponse(result);
// process response
TestComplete(); // async test complete
});
}, null);
}
}
Do I need to implement the IAsync interface or something similar?
I'd like to have it do something like this:
using System;
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;
[TestClass]
public class WebRequestsTests : WorkItemTest
{
[TestMethod, Asynchronous]
public void TestWebRequest()
{
MyThread thread = new MyThread();
thread.Start(result =>
{
EnqueueCallback(() =>
{
WebResponse response = thread.EndGetResult(result);
// process response
TestComplete(); // async test complete
});
}, null);
}
}
Not sure I'm also 100% comfortable with the lambda expressions either, so if those are removed, even better! ;)
Thanks
You don't need to create a new thread to deal with the EndRequest or EndResponse callback - these will be called for you on a background thread from the ThreadPool. So something like your first code example should work.
If you don't like the nested lambdas just declare named methods :). You can pass state information in the Begin... methods which you can retrieve in the result object.
What you're asking is kind of weird - you're wrapping an async framework with sync version, and rewrapping that with an async version. It sounds like you're creating extra work for yourself in order to stay faithful to your port. You will also use some extra memory to keep an extra thread alive doing nothing (1MB for the stack at least).
If you still want to do it check out this link though.