WP7 Background Agent Pitfalls and App/Agent Synchronization

To put this post into perspective see Windows Phone 7 App Development Helpers and Time Savers.

Background agents are a very important feature for WP7 apps. Agents allow you to run code in background while the app is not running – and also while it is running.

Some pitfalls you should bear in mind:

  • Beware of misleading agent memory usage reported under the debugger.
  • Create an appropriate VS solution structure to comply with unsupported APIs.
  • Web request default timeouts might be too long for agent duration constraint.
  • App/Agent communication must be synchronized.
  • VB.NET agent template bug.

Misleading agent memory usage under the debugger

PeriodicAgents have memory limit of 6MB. Agent duration and memory constraints are not enforced when debugging. With the debugger attached DeviceStatus reports a way higher memory usage then without the debugger. For an empty PeriodicTask DeviceStatus.ApplicationPeakMemoryUsage reports 3.5 MB with the debugger and 1.8 MB without the debugger. To get your agents real memory usage write to IsolatedStorage or a Tile or show a Toast.

VS solution structure

Some APIs like Phone.Shell are unsupported in Agents. Because the submission process enforces this using static code analysis, your submission will not only fail when using an unsupported API, but also when you simply reference it. To avoid painful refactorings, you should plan your solution structure accordingly from the beginning on.

The solution structure of the demo application is optimized to adhere to the agent API and resource constraints. The projects are numbered to show the reference hierarchy.

Solution structure optimized for Agent API and memory constraints

VB.NET agent template bug

With VB.NET Visual Studio, Add Agent Project creates a Class ScheduledAgent with an invalid constructor. I wrongly names the constructor Sub ScheduledAgent(), correctly it  should be Sub New(). This bug results in your error handler never being registered and might lead to your agent being disabled on the users phone without you ever knowing.

Web request default timeouts might be too long for agent duration constraint

PeriodicAgents are constraint to 25 sec duration. WebClient and HttpWebRequest seem to have a default timeout of approx. 20 sec. Because both do not support to set at timeout you should consider implementing a timeout manually. When doing so, don’t forget the ignore WebExceptions with WebExceptionStatus.RequestCanceled that might arrive after cancelling.

App/Agent communication must be synchronized

Microsoft’s recommendations for app/agent communications are very strict: For one-direction communication where the foreground application writes and the agent only reads, we recommend using an isolated storage file with a Mutex. … We recommend that you do not use IsolatedStorageSettings to communicate between processes because it is possible for the data to become corrupt“.

The following sample uses a Mutex for synchronization:

Public Class IsolatedStorageFile
    Public Shared SerializationFormatter As SerializationFormatter = SerializationFormatter.Binary
    'Beware! XmlSerializer can not seriallize TimeSpan
    'Public Shared SerializationFormatter As SerializationFormatter = Threading.SerializationFormatter.DataContract

    Private Const _timoutToPreventBlocking As Integer = 5 * 1000

    Public Shared Sub WriteSynchronized(filePath As String, fileContent As Object)
        filePath = SetFileNameExtension(filePath)

        Dim mutex As New Mutex(False, filePath)
        Try
            If mutex.WaitOne(_timoutToPreventBlocking) Then
                Using isoFile = IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication(),
                        isoStream = isoFile.OpenFile(filePath, FileMode.Create)
                    Select Case SerializationFormatter
                        Case SerializationFormatter.Binary
                            SilverlightSerializer.Serialize(fileContent, isoStream)
                        Case SerializationFormatter.XML
                            Dim serializer = New XmlSerializer(fileContent.GetType)
                            serializer.Serialize(isoStream, fileContent)
                        Case SerializationFormatter.DataContract
                            Dim serializer = New DataContractSerializer(fileContent.GetType)
                            serializer.WriteObject(isoStream, fileContent)
                    End Select
                End Using
            Else
                'This should never happen. The phone runtime even releases mutexes for aborted processes. But better safe than sorry!
                Dim ex As New ThreadStateException("Unable to acquire mutex for app/agent sync")
                Trace.Error(ex.Message)
                Throw ex
            End If
        Finally
            mutex.ReleaseMutex()
        End Try
    End Sub

    Public Shared Function ReadSynchronized(Of contentType)(filePath As String) As contentType
...
    End Function

End Class
Posted in Computers and Internet | Tagged , | Leave a comment

Windows Phone 7 App Development Helpers and Time Savers

Für mehr Informationen zu diesem Thema in Deutsch siehe meine kommenden Artikel “Phone, Schweiß und Tränen” und “Aus App-Gründen ans Licht” im dotnetpro Magazin, Ausgaben 9 und 10/2012.

The Windows Phone is a fascinating app platform and Microsoft’s Visual Studio / Blend toolset is extremely powerful, but Silverlight can be a huge time sink and developing for the Windows Phone adds some. To  help streamlining your WP7 app development I am sharing some helpful experiences from developing my Currencies app.
Download sample code.
View Currencies demo video.

Balsamiq UI Sketch and Screenshot of Published App

Links to all posts of this series [I will add the missing posts as I find time to do so]:

  • User Experience
  • App Architecture
  • No MVVM
  • Development Tools
  • Fast Launch and Fluid UX
  • Asynchronous Web Requests
  • Use Tracing to understand your Apps Event Sequences
  • Good Error Handling
  • Agent Pitfalls and App/Agent Synchronization
  • Keypad (SIP) Tips
Posted in Computers and Internet | Tagged , | Leave a comment

Managing BLOBs using SQL Server FileStream via EF and WCF streaming

Für mehr Informationen zu diesem Thema in Deutsch siehe meinen Artikel “Stream das BLOB” im dotnetpro Magazin 6/2012.

With FileStream SQL Server 2008+ stores BLOBs in the NTFS file system instead of its table store and offers fast streaming access.

This post shows how to manage FileStream BLOBs via the Entity Framework (EF 4.1) DbContext API and how to stream them via Windows Communication Foundation (WCF).
Download sample code.
View UI demo video.

The main options for storing large objects (BLOBs) in SQL Server are:

  • Store BLOB in a DB table.
  • Store BLOB via FileStream in NTFS.
  • Store BLOB via FileTable in NTFS.
  • Store File in NTFS with a reference to its path in a DB Table.

If you prefer to manually store your BLOBs as NFTS Files consider adding transaction support, see Using Transactional NTFS (TxF) with SQL Server in .NET.

BLOB storage options

Continue reading

Posted in Computers and Internet | Tagged , , , , , , | 4 Comments

Using Transactional NTFS (TxF) with SQL Server in .NET

I just stumbled across the very new Transactional NTFS (TxF) .NET managed wrapper by Pietro Partescano and gave it a try.

TxF offers transactional protection for NTFS operations:

  • Atomic operations on single files.
    Makes writing files more robust.
  • Transactions for multi-file operations.
    Concurrent readers only see committed operations.
    Works with remote file shares too.
  • The TxF resource manager can participate in heterogeneous distributed transactions.
    Ex: spanning NFTS, SQL Server and MSMQ operations.

MSDN: About Transactional NTFS
MSDN Magazine article: Enhance Your Apps With File System Transactions
Wikipedia: Transactional NTFS

Sample using NTFS Transaction with SQL Server

CREATE TABLE [dbo].[DocumentLink](
	[DocumentID] [uniqueidentifier] ROWGUIDCOL primary key  NOT NULL,
	[Name] [varchar](255) UNIQUE  NOT NULL,
	[Type] [varchar](5) NULL)
Imports System.Transactions

Module Module1
    Private _testFolderPath = IO.Path.Combine(IO.Directory.GetParent(My.Application.Info.DirectoryPath).Parent.FullName, "TestFiles")

    Sub Main()
        Try
            Using tsc As New TransactionScope(TransactionScopeOption.RequiresNew,
                                              New TransactionOptions With {.IsolationLevel = IsolationLevel.ReadCommitted}),
                  DB As New FileStreamTestEntities

                'Create file in NTFS
                Dim filePath = IO.Path.Combine(_testFolderPath, "TestFile1.txt")
                Dim content = System.Text.Encoding.UTF8.GetBytes("My test data")
                Dim fileHandle = TxF.File.CreateAndWriteFile(filePath, TxF.File.CreationDisposition.CreatesNewfileAlways, content)

                'Insert link to file in database table
                DB.DocumentLinks.Add(New DocumentLink With {.DocumentID = Guid.NewGuid, .Name = filePath})
                DB.SaveChanges()

                tsc.Complete()
            End Using
            Console.WriteLine("done")
        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        Finally
            Console.ReadLine()
        End Try
    End Sub

End Module
Posted in Computers and Internet | Tagged , , , , | Leave a comment

How to get the best currency exchange rate when travelling

[ 27 April 2013: Updated infos about the “dynamic currency conversion” scam.]
[ 07 July 2013: Foreign transaction fees are not applied to cash withdrawals, only to purchases with the card. ]
[ 23 Nov 2015: Added Cortana search tip ]
[ 24 Mar 2016: Updated some links ]
[ 05 Apr 2016: Starting 1 June 16 DKB no longer refunds international non-customer fees.
I consider this change understandable. ]
[ 17 Jun 2018: Added Santander 1Plus card ]

  1. Research the current exchange rate:
    OANDA Web Currency Converter.
    LeanWork Multi-Currency Converter App for Windows Phone and Windows 10.
    First Data rates (used by DKB).
  2. Know your  card fees:
    ATM non-customer fee: 1$ to 6$.
    Foreign transaction fee: 1.0% to 3,5% .
  3. For cash withdrawals use ATMs with your debit card:
    Works in almost all countries.
    At ATMs with the Maestro or Cirrus logo.
    MaestroLogoCirrusLogo
    Most banks charge a non-customer fee (ex. 4$) .
    No foreign transaction fee!
    No cash advance fee!
    No advance interest rate!
    To find the next ATM perform a Cortana search “find atm”:
    SearchATM
  4. Do not(!) use credit card cash withdrawals
    Beware of cash advance fee: 2% to 4 % or flat fee.
    Beware of interest rate: 5% to 20+%. Commonly there is no grace period, you start paying interest right away!
    Use in an emergency only. Better find a store that offers cash back on purchases.
  5. Avoid exchange kiosks and counters.
    They usually offer worse exchange rates than ATMs, Banks and post offices.
  6. Consider using credit cards for large purchases like airline tickets, hotel bills, car rentals and in restaurants.
    With some merchants charging a fee for credit card transactions sometimes it is cheaper to walk to the next ATM and pay cash.
  7. Traveller’s cheques are one of the most secure methods of carrying your money abroad.
    I find them too inconvenient to use.
    ATMs usually offer better exchange rates and lower fees
  8. Beware of “dynamic currency conversion”: Some local merchants (especially hotels) try to charge your credit card in your home currency (ex: USD) instead of the local currency (ex: THB) using a bad exchange rate. Insist on paying in the local currency.
    You can check current and historic credit card exchange rates here:
    MasterCard conversion rates
    Visa conversion rates
    First Data conversion rates (used by DKB)

I use the DKB-VISA-Card with ATMs when traveling:

dkb

  • I am using DKB as my primary bank account since 2007
  • The DKB-VISA-Card is a credit card with debit card conditions
  • No non-customer fee in Germany
  • No non-customer fee (worldwide)
    In case a foreign bank still does charge a fee (ex: all ATMs in Thailand charge 150THB per withdrawal) DKB does refund it upon request.
  • No cash advance fee!
  • No advance interest rate!
  • No foreign transaction fee (for active customers only)!

In countries where banks charge a non-customer fee (e.g. 220THB per withdrawal in Thailand and 250PHP in Philippines) I prefer the Santander 1Plus Visa card to withdraw from ATMs. The 1Plus is the only card I know of where one still can get a refund for non-customer fees. To get a refund send an email with a photo to the ATM receipts to karteninhaberservice@santander.de. Sadly with the 1Plus I have to go to ATMs more often than I like because it has a daily limit of 300€ (in contrast to 1000€ with the DKB Visa card).

With the 1Plus card beware!

  • Santander no longer allows to automatically balance out the 1Plus card from a reference account. To avoid accidentally paying interest (Santander sneakily does not even send an email when a payment is due) I always transfer enough money to the 1Plus before withdrawing.
  • You must request non-customer fee refunds within six weeks after withdrawal.
Posted in Leisure | 2 Comments

Changing the email send address in Office 365 without moving your domain

Using Office 365 Exchange Online for your email while leaving the hosting with your existing hosting provider is not as straightforward as one might expect.

Reasons for using Office 365 while staying with my current email hosting provider are:

  • I want to use Office 365 Online because of its higher storage limit, to manage tasks integrated with my Windows Phone (see: Synchronize Windows Phone with Outlook Emails, Contacts, Calendar and Tasks) – the Mango beta is supposed to include a Tasks app – and to move away from Gmail (because I do not like them scanning my e-mail).
  • I want to stay with my current hosting provider internet24.debecause they have worked flawlessly for years and I want my emails in redundantly in at least two locations as a precaution for service outages. Remember: the 99.9% availability guaranteed by Office 365 allows for ~8h/year downtime.
  • Simply connecting from Office 365 to my existing email server via IMAP is not an option, because I do frequently exceed the storage limit of my current e-mail hosting provider which causes the server to delete old emails – which sadly results in those messages being deleted on the client too(!).

Migrating from Gmail to Office 365 while staying with current email hosting provider

With Office 365 you can not simply configure a reply-to address (like you can in Gmail). My e-mail domain is petermeinl.de. My Office 365 domain is leanwork.onmicrosoft.com.
By default Office 365 uses pit@leanwork.onmicrosoft.com as send address for my emails and recipients will reply to this address. I wanted to change the send address to pit@petermeinl.de.

I used the following steps to change my email send address from pit@leanwork.onmicrosoft.com  to pit@petermeinl.de:

  1. Verify email domain petermeinl.de in Office 365 using “Admin, Domains, Add a domain”. Cancel the wizard after verifying the domain and before moving it (don’t click Next)!
  2. Install Microsoft Online Services Module for Windows PowerShell.
    For background information and prerequisites see Use Windows PowerShell to manage Office 365
  3. Change the email send address via PowerShell
import-module MSOnline
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://pod51013psh.outlook.com/PowerShell-LiveID?PSVersion=2.0 -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Set-Mailbox  pit@leanwork.onmicrosoft.com -EmailAddresses SMTP:pit@petermeinl.de, pit@leanwork.onmicrosoft.com

To copy my existing emails to Office 365 and to keep get new ones I:

  1. Copied all existing emails from Gmail to Office 365 via the Exchange email migration tool for IMAP mailboxes.
  2. Configured email forwarding from internet24.de to Office 365 via the internet24.de admin site.
Posted in Computers and Internet | Tagged , , | 27 Comments

Using Native VHD Boot

Windows 7  and Server 2008 support booting a physical machine from a virtual hard disk (VHD). This post describes the easiest way to create a multi-boot system using native VHD boot and how to use the VHD on multiple machines.

Options to work with multiple OSes on one physical machine are:

  • Multi-boot using a separate disk partition for each OS
  • Run multiple virtual machine guests in a physical host OS
  • Multi-boot using virtual hard disks (native VHD boot)

The advantages of native VHD boot are:

  • It uses physical hardware.
    The performance penalty of using a VHD vs a native disk is negligible.
  • No need for a separate partition.
  • Less disk space needed.
    When using a dynamic VHD, the VHD occupies its defined size only while being used. When the OS booted from the VHD is shut down, the VHD only occupies the space actually written to it.
    Ex: a clean 2008 Server dynamic VHD needs a minimum of 40 GB when running and approx. 9GB when shut down.
  • Possibility to use a copy of the VHD on different computers.
    Ex: workstation and notebook
  • Possibility to use the VHD as virtual machine under XP-Mode or Hyper-V.

Continue reading

Posted in Computers and Internet | Tagged , | 3 Comments