I have a TextBlock on my Windows 8.1 application:
<TextBlock x:Name="some" Text="" TextWrapping="Wrap" />
And I have a code:
some.Text = "example 1";
// working with web service
some.Text = "example 2";
// working with database
When I launch my code I see only "example 1" message. The message "example 2" I can see only after database operation complete.
Is there any way on Windows 8.1 to redraw/refresh/update UI element?
Update:
Here is database operation:
foreach(var record in records)
{
SqliteController.InsertRecord(record);
}
....
public void async InsertRecord(Inspection record)
{
connection.InsertAsync(inspection);
}
Your UI thread seems to be blocked, thus it isn't updeted right away. I've not seen all the code, but from this what you have shown seems that connection.InsertAsync(inspection); is an asynchronous operation. Probably in this situation it may be sufficient just to await your procedure:
foreach (var record in records)
{
await SqliteController.InsertRecord(record);
}
You can also think of redirecting heavy job to other thread, for example like this:
Task.Run(() =>
{
foreach (var record in records)
SqliteController.InsertRecord(record);
});
You may also think of using Paraller.ForEach to speed up your operation.
As for asynchronous programming you will find many usefull information at MSDN and Stephen Cleary's blog.
Related
I am trying to make conference with Voximplant, and when user makes a call to another user, while the call is still going on, it makes another call to another user making two calls and the callees is added to a video conferencing.
But it seems the caller is billed twice and the scenerio doesnt look optimised. What should i do to bill once and optimize it?
Scenario:
require(Modules.Conference);
var call, conf = null;
VoxEngine.addEventListener(AppEvents.Started, handleConferenceStarted);
function handleConferenceStarted(e) {
// Create 2 conferences right after session to manage audio in the right way
if( conf === null ){
conf = VoxEngine.createConference(); // create conference
}
conf.addEventListener(CallEvents.Connected,function(){
Logger.write('Conference started')
})
}
VoxEngine.addEventListener(AppEvents.CallAlerting, function(e) {
e.call.addEventListener(CallEvents.Connected, handleCallConnected);
let new_call = VoxEngine.callUser(e.destination,e.callerid,e.displayName,{},true)
new_call.addEventListener(CallEvents.Connected,handleCallConnected);
e.call.answer();
});
function handleCallConnected(e) {
Logger.write('caller connected');
conf.add({
call: e.call,
mode: "FORWARD",
direction: "BOTH", scheme: e.scheme
});
}
You need to end the conference when there are no participants. Refer to the following article in our documentation: https://voximplant.com/docs/guides/conferences/howto. You can find the full scenario code there.
Additionally, I recommend to add some handlers for the CallEvents.Disconnected and the CallEvent.Failed events right after
new_call.addEventListener(CallEvents.Connected,handleCallConnected);
because sometimes the callee may be offline or press a reject button. 🙂
Can anyone help me to understand why the following code is blocking the UI thread...
I've modified the sample application from https://github.com/TrevorDArcyEvans/BlazorSQLiteWasm in order to test the performance of the SQLite database inside a Blazor WebAssembly Progressive Web Application
On a .razor file I have the following
<button onclick="#(async () => CreateMany())" class="btn btn-default btn-sm">
Insert Many
</button>
Which references:
private async void CreateMany()
{
var cars = new List<Car>();
for (int i = 0; i < 1000; i++)
{
cars.Add(new() { Brand = "BMW", Price = 500 });
}
var db = await _dbContextFactory.CreateDbContextAsync();
await db.Cars.AddRangeAsync(cars);
await db.SaveChangesAsync();
_cars.Clear();
_cars.AddRange(db.Cars);
StateHasChanged();
}
When I click the "Insert Many" button it seems to ignore the fact the it's an async void, and it blocks the UI anyway. Am I missing something here?
.NET 6.0
onclick="#(async () => CreateMany())"
This will give you a "... is not awaited" Warning after a Build. Just use onclick="CreateMany"
Am I missing something here?
It would have been better to use async Task CreateMany() ... but that is not essential.
The main problem is that Sqlite is totally synchronous. await db.SaveChangesAsync(); is a lie, it is not async at all.
So your code would probably work as expected with a different database, but there is not much on offer in Wasm.
Task.Run() is also not effective, so alas, you're stuck with this.
Worklight busyindicator not working properly.My isssue is i'm using multipage.On page change i call adapter for webservice and call busy indicator so that it show work in progress while fetching.but what happen is page change and indicator show and hide quickly but adpater still in fetching phase and after sometime data called successfully but during these working no busy indicator shows.
var busyIndicator = null;
function wlCommonInit(){
busyIndicator = new WL.BusyIndicator();
}
This is the code i call on page change.
busyIndicatorDemo();
var viewPath = "views/add_fund_transfer.html";
WL.Page.load(viewPath,
{
onComplete: function() {
PayAnyOne_Controller.GetBranches(GetBranchesProcedureName);
busyIndicator.hide();
}
});
function busyIndicatorDemo() {
busyIndicator.show();
setTimeout(15000);
}
its seems like busyindicator doesn't work with adpater when using in multipage.
Please give me the solution or the problem in my code.
Thanks.
It seems like the problem is in the flow of the code. you're running this code basically:
show busy indicator
load page
when page has finished loading: invoke procedure (async call), and hide busyindicator.
So this generates the behavior you've reported - the busyindicator is shown and quickly hidden once the page has finished loading, even though the service is still fetching data (in an async call)
moving the busyindicator.hide to the onSuccess of the invoke procedure should solve the problem (put it also in the onFailure ...)
Hope this helps
I have an app that uses RavenDB. It has a WPF front-end GUI app. I would like for that app to be notified of certain types of new documents. For example, if my app loads the most recent 50 Foos for display, and someone else adds 10 more Foos later, I would like the app to know about these new 10 and update the UI.
I could poll the DB every few seconds to check for new documents, but it would be nice to have a real-time, two-way call-back notification from RavenDB. Does this functionality exist?
My searches have ended with smuggler and listeners, but I don't know that either is intended for this purpose.
RavenDB V2 will support push notifications:
store.Changes()
.ForDocument("users/1")
.Subscribe(notification => {
using(var session = store.OpenSession())
{
var user = session.Load<User>(notification.Name);
Console.WriteLine("Wow! " + notification.Name + " changed. New name: " + user.Name);
}
});
I've been trying to send data from my background page to a content script in my chrome extension. i can't seem to get it to work. I've read a few posts online but they're not really clear and seem quite high level. I've got managed to get the oauth working using the Oauth contacts example on the Chrome samples. The authentication works, i can get the data and display it in an html page by opening a new tab.
I want to send this data to a content script.
i'm having a lot of trouble with this and would really appreciate if someone could outline the explicit steps you need to follow to send data from a bg page to a content script or even better some code. Any takers?
the code for my background page is below (i've excluded the oauth paramaeters and other )
` function onContacts(text, xhr) {
contacts = [];
var data = JSON.parse(text);
var realdata = data.contacts;
for (var i = 0, person; person = realdata.person[i]; i++) {
var contact = {
'name' : person['name'],
'emails' : person['email']
};
contacts.push(contact); //this array "contacts" is read by the
contacts.html page when opened in a new tab
}
chrome.tabs.create({ 'url' : 'contacts.html'}); sending data to new tab
//chrome.tabs.executeScript(null,{file: "contentscript.js"});
may be this may work?
};
function getContacts() {
oauth.authorize(function() {
console.log("on authorize");
setIcon();
var url = "http://mydataurl/";
oauth.sendSignedRequest(url, onContacts);
});
};
chrome.browserAction.onClicked.addListener(getContacts);`
As i'm not quite sure how to get the data into the content script i wont bother posting the multiple versions of my failed content scripts. if I could just get a sample on how to request the "contacts" array from my content script, and how to send the data from the bg page, that would be great!
You have two options getting the data into the content script:
Using Tab API:
http://code.google.com/chrome/extensions/tabs.html#method-executeScript
Using Messaging:
http://code.google.com/chrome/extensions/messaging.html
Using Tab API
I usually use this approach when my extension will just be used once in a while, for example, setting the image as my desktop wallpaper. People don't set a wallpaper every second, or every minute. They usually do it once a week or even day. So I just inject a content script to that page. It is pretty easy to do so, you can either do it by file or code as explained in the documentation:
chrome.tabs.executeScript(tab.id, {file: 'inject_this.js'}, function() {
console.log('Successfully injected script into the page');
});
Using Messaging
If you are constantly need information from your websites, it would be better to use messaging. There are two types of messaging, Long-lived and Single-requests. Your content script (that you define in the manifest) can listen for extension requests:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == 'ping')
sendResponse({ data: 'pong' });
else
sendResponse({});
});
And your background page could send a message to that content script through messaging. As shown below, it will get the currently selected tab and send a request to that page.
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: 'ping'}, function(response) {
console.log(response.data);
});
});
Depends on your extension which method to use. I have used both. For an extension that will be used like every second, every time, I use Messaging (Long-Lived). For an extension that will not be used every time, then you don't need the content script in every single page, you can just use the Tab API executeScript because it will just inject a content script whenever you need to.
Hope that helps! Do a search on Stackoverflow, there are many answers to content scripts and background pages.
To follow on Mohamed's point.
If you want to pass data from the background script to the content script at initialisation, you can generate another simple script that contains only JSON and execute it beforehand.
Is that what you are looking for?
Otherwise, you will need to use the message passing interface
In the background page:
// Subscribe to onVisited event, so that injectSite() is called once at every pageload.
chrome.history.onVisited.addListener(injectSite);
function injectSite(data) {
// get custom configuration for this URL in the background page.
var site_conf = getSiteConfiguration(data.url);
if (site_conf)
{
chrome.tabs.executeScript({ code: 'PARAMS = ' + JSON.stringify(site_conf) + ';' });
chrome.tabs.executeScript({ file: 'site_injection.js' });
}
}
In the content script page (site_injection.js)
// read config directly from background
console.log(PARAM.whatever);
I thought I'd update this answer for current and future readers.
According to the Chrome API, chrome.extension.onRequest is "[d]eprecated since Chrome 33. Please use runtime.onMessage."
See this tutorial from the Chrome API for code examples on the messaging API.
Also, there are similar (newer) SO posts, such as this one, which are more relevant for the time being.