I'm tasked with creating a tool to help set up customers systems easily. I've created a function that calls a chocolatey script through powershell in c# and I use Task.run to create a new thread so it doesn't affect the UI thread, The system works fine, but I'm having problems with some computers. It's not helped that I have no access to these computers and do not know much about their system, and due to time constraints do not have access to these computers. I do know they have windows 8.1. I was given a windows 10 virtual machine to test on (which I still don't understand as it was known that this was a windows 8 problem)
Here is the code.
I know for a fact(due to the one time I was given access to these computers) that it stops on Task.Run(() => task)
Does anyone know if there are any problems with either chocolatey or Tasks on windows 8.1?
Task callTask = Task.Run(() => ExecuteAsynchronouslyAsync("chocolatey string", CheckBox box, string logName));
public async Task<PowerShellAction> ExecuteAsynchronouslyAsync(String commandStr, CheckBox box, string logName)
{
powerShellAction = new PowerShellAction();
powerShellAction.isFinished = false;
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript(commandStr); // adding the script to the powershell script.
outputCollection = new PSDataCollection<PSObject>();
outputCollection.DataAdded += OutputData;
IAsyncResult result = ps.BeginInvoke<PSObject, PSObject>(null, outputCollection);
PSDataCollection<PSObject> execRes = await Task.Factory.FromAsync(result, ps.EndInvoke);
}
return powerShellAction;
}
Working right now on trying to get a virtual machine of 8.1 to continue trying to debug myself. Any other suggestions would be welcome.
Unfortunately I cannot ensure that my suggestions are correct. The main reason is, that i can't figure out what PowerShellAction is supposed to be. I'm assuming here that PowerShell is System.Management.Automation.PowerShell.
I'm suggesting several things:
Your code does not compile for several reasons: you have no var or type-declaration on the first line of your method and the method-call would not work because of the addition string keyword. Try to avoid pasting in code like yours in the future please because it's pretty hard to rebuild your sample.
Don't bypass a UI control to an async method but use the needed value (e.g. box.IsChecked as a bool) instead.
Add ConfigureAwait(false) to your await to prevent .NET from trying to sync back to the context.
Take more care about exception handling insude of your method.
Dont' return anything if you don't need it in your method.
The code (untestet) could be something like this:
var task = Task.Run(() => ExecutePowerShellAsync("chocolatey string", box.IsChecked, "NameOfTheLog"));
public async Task<PowerShellAction> ExecutePowerShellAsync(String commandStr, bool checkBoxValue, string logName)
{
var powerShellAction = new PowerShellAction();
powerShellAction.isFinished = false;
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript(commandStr); // adding the script to the powershell script.
var outputCollection = new PSDataCollection<PSObject>();
outputCollection.DataAdded += OutputData;
IAsyncResult result = ps.BeginInvoke<PSObject, PSObject>(null, outputCollection);
PSDataCollection<PSObject> execRes = await Task.Factory.FromAsync(result, ps.EndInvoke).ContinueWith(t => {
if (t.IsFaulted)
{
System.Diagnostics.Trace.TraceError("Task faulted with exception: " + t.Exception?.Message);
}
return t.Result;
}).ConfigureAwait(false);
}
return powerShellAction;
}
I use ContinueWith in order to be able to react to any exception that might occur inside the original task.
I'm suggesting this because your description smells like you have a typical thread-lock which means the code simple does not come back due to an exception or context-syncing-problems.
Related
I have this method which is using ODBC and executes the reader async but the method is still blocking my UI for some reason it's loading 4000 records but I am wondering if someone can look at my code see where I am going wrong.
async Task<BindingList<PurchaseLinkHeaderC>> GetPurchaseOrders( IProgress<int> progress)
{
BindingList<PurchaseLinkHeaderC> _purhcaseOrderList = new BindingList<PurchaseLinkHeaderC>();
try
{
string sageDsn = ConfigurationManager.AppSettings["SageDSN"];
string sageUsername = ConfigurationManager.AppSettings["SageUsername"];
string sagePassword = ConfigurationManager.AppSettings["SagePassword"];
//using (var connection = new OdbcConnection("DSN=SageLine50v24;Uid=Manager;Pwd=;"))
using (var connection =
new OdbcConnection(String.Format("DSN={0};Uid={1};Pwd={2};", sageDsn, sageUsername, sagePassword)))
{
connection.Open();
string fromD = dtpFrom.Value.ToString("yyyy-MM-dd");
string toD = dtpTo.Value.ToString("yyyy-MM-dd");
string SQL =
"SELECT 'ORDER_NUMBER', 'ORDER_OR_QUOTE', 'ORDER_DATE', 'DELIVERY_DATE', 'ORDER_STATUS_CODE', 'ORDER_STATUS', 'DELIVERY_STATUS_CODE', 'DELIVERY_STATUS', 'ACCOUNT_REF', 'NAME', 'ADDRESS_1', 'ADDRESS_2', 'ADDRESS_3', 'ADDRESS_4', 'ADDRESS_5', 'C_ADDRESS_1', 'C_ADDRESS_2', 'C_ADDRESS_3', 'C_ADDRESS_4', 'C_ADDRESS_5', 'DEL_NAME', 'DEL_ADDRESS_1', 'DEL_ADDRESS_2', 'DEL_ADDRESS_3', 'DEL_ADDRESS_4', 'DEL_ADDRESS_5', 'VAT_REG_NUMBER', 'REFERENCE', 'CONTACT_NAME', 'TAKEN_BY', 'SUPP_ORDER_NUMBER', 'SUPP_TEL_NUMBER', 'NOTES_1', 'NOTES_2', 'NOTES_3', 'SUPP_DISC_RATE', 'FOREIGN_ITEMS_NET', 'FOREIGN_ITEMS_TAX', 'FOREIGN_ITEMS_GROSS', 'ITEMS_NET', 'ITEMS_TAX', 'ITEMS_GROSS', 'TAX_RATE_1', 'TAX_RATE_2', 'TAX_RATE_3', 'TAX_RATE_4', 'TAX_RATE_5', 'NET_AMOUNT_1', 'NET_AMOUNT_2', 'NET_AMOUNT_3', 'NET_AMOUNT_4', 'NET_AMOUNT_5', 'TAX_AMOUNT_1', 'TAX_AMOUNT_2', 'TAX_AMOUNT_3', 'TAX_AMOUNT_4', 'TAX_AMOUNT_5', 'COURIER_NUMBER', 'COURIER_NAME', 'CONSIGNMENT', 'CARR_NOM_CODE', 'CARR_TAX_CODE', 'CARR_DEPT_NUMBER', 'CARR_DEPT_NAME', 'FOREIGN_CARR_NET', 'FOREIGN_CARR_TAX', 'FOREIGN_CARR_GROSS', 'CARR_NET', 'CARR_TAX', 'CARR_GROSS', 'FOREIGN_INVOICE_NET', 'FOREIGN_INVOICE_TAX', 'FOREIGN_INVOICE_GROSS', 'INVOICE_NET', 'INVOICE_TAX', 'INVOICE_GROSS', 'CURRENCY', 'CURRENCY_TYPE', 'EURO_GROSS', 'EURO_RATE', 'FOREIGN_RATE', 'SETTLEMENT_DUE_DAYS', 'SETTLEMENT_DISC_RATE', 'FOREIGN_SETTLEMENT_DISC_AMOUNT', 'FOREIGN_SETTLEMENT_TOTAL', 'SETTLEMENT_DISC_AMOUNT', 'SETTLEMENT_TOTAL', 'PAYMENT_REF', 'PRINTED', 'PRINTED_CODE', 'POSTED', 'POSTED_CODE', 'QUOTE_STATUS_ID', 'RECURRING_REF', 'DUNS_NUMBER', 'PAYMENT_TYPE', 'BANK_REF', 'GDN_NUMBER', 'PROJECT_ID', 'ANALYSIS_1', 'ANALYSIS_2', 'ANALYSIS_3', 'INVOICE_PAYMENT_ID', 'RESUBMIT_INVOICE_PAYMENT_REQUIRED', 'RECORD_CREATE_DATE', 'RECORD_MODIFY_DATE', 'RECORD_DELETED' FROM 'PURCHASE_ORDER' WHERE ORDER_DATE >='{0}' and ORDER_DATE <='{1}'";
int counter = 0;
using (var command = new OdbcCommand(string.Format(SQL, fromD, toD), connection))
{
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
var purhcaseOrders = new PurchaseLinkHeaderC();
if ((reader["ORDER_NUMBER"] != ""))
{
counter++;
string orderNumber = Convert.ToString(reader["ORDER_NUMBER"]);
purhcaseOrders.Order_Number = OrderNumber.ToString();
purhcaseOrders.PurchaseOrderNo = Convert.ToInt32(reader["ORDER_NUMBER"]);
purhcaseOrders.Name = reader["NAME"].ToString();
purhcaseOrders.Selected_PurchaseOrder = false;
_purhcaseOrderList.Add(purhcaseOrders);
}
}
}
}
}
}
catch (Exception ex)
{
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info(ex, "Error at GetSalesOrders " + ex.ToString());
}
return _purhcaseOrderList;
}
I want to be able to show a progress bar of the list being loaded so I was attempting to call it as this way. But I am not sure how to attach the progress method either.
var progressIndicator = new Progress<int>(ReportProgress);
//call async method
BindingList<PurchaseLinkHeaderC> purchaseOrders = await GetPurchaseOrders(progressIndicator);
_masterPurchaseOrders = purchaseOrders;
I am hoping that someone can help here.
When you await, the default behaviour is to use the sync-context, if one, when coming back from the async operation. In the case of a UI application, the sync-context is: the UI.
So; right now, there are a lot of things that come back to the UI. This is useful when context matters, but in your case: it doesn't - since you are simply returning a list.
This means that you should be able to add .ConfigureAwait(false) to a lot of those await expressions - for example:
while (await reader.ReadAsync().ConfigureAwait(false))
This disconnects the sync-context behaviour, and may improve what you are seeing. You would ideally to add that to all of the await calls in the utility method (GetPurchaseOrders).
You may also wish to look for any missing async operations - for example, the connection.Open(); could be a await connection.OpenAsync().ConfigureAwait(false);
Note that the calling code should not use ConfigureAwait(false) - since the binding-list touches the UI, it needs the sync-context. So: don't add ConfigureAwait(false) to the await GetPurchaseOrders(...) call.
There is also one other possibility: you say that you are using ODBC and "sage". It is entirely possible that the ODBC/sage API doesn't support await, and it is being implemented as "sync over async". If this is the case, it gets tricky. You might need to use a thread instead of async/await in that case - perhaps via ThreadPool.QueueUserWorkItem. There are ways to invoke async code on worker threads, but if the "async" code is actually "sync code that pretends to be async", there's not really any point, and you might as well do it "the old way". This usually means:
start a worker (ThreadPool)
do some work on the worker (your existing code, but perhaps using the non-async implementation)
at the end of the worker, use Control.Invoke to push the work back to the UI thread for the final "update the UI" step
I need to test if there's any memory leak in our application and monitor to see if memory usage increases too much while processing the requests.
I'm trying to develop some code to make multiple simultaneous calls to our api/webservice method. This api method is not asynchronous and takes some time to complete its operation.
I've made a lot of research about Tasks, Threads and Parallelism, but so far I had no luck. The problem is, even after trying all the below solutions, the result is always the same, it appears to be processing only two requests at the time.
Tried:
-> Creating tasks inside a simple for loop and starting them with and without setting them with TaskCreationOptions.LongRunning
-> Creating threads inside a simple for loop and starting them with and without high priority
-> Creating a list of actions on a simple for loop and starting them using
Parallel.Foreach(list, options, item => item.Invoke)
-> Running directly inside a Parallel.For loop (below)
-> Running TPL methods with and without Options and TaskScheduler
-> Tried with different values for MaxParallelism and maximum threads
-> Checked this post too, but it didn't help either. (Could I be missing something?)
-> Checked some other posts here in Stackoverflow, but with F# solutions that I don't know how to properly translate them to C#. (I never used F#...)
(Task Scheduler class taken from msdn)
Here's the basic structure that I have:
public class Test
{
Data _data;
String _url;
public Test(Data data, string url)
{
_data = data;
_url = url;
}
public ReturnData Execute()
{
ReturnData returnData;
using(var ws = new WebService())
{
ws.Url = _url;
ws.Timeout = 600000;
var wsReturn = ws.LongRunningMethod(data);
// Basically convert wsReturn to my method return, with some logic if/else etc
}
return returnData;
}
}
sealed class ThreadTaskScheduler : TaskScheduler, IDisposable
{
// The runtime decides how many tasks to create for the given set of iterations, loop options, and scheduler's max concurrency level.
// Tasks will be queued in this collection
private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
// Maintain an array of threads. (Feel free to bump up _n.)
private readonly int _n = 100;
private Thread[] _threads;
public TwoThreadTaskScheduler()
{
_threads = new Thread[_n];
// Create unstarted threads based on the same inline delegate
for (int i = 0; i < _n; i++)
{
_threads[i] = new Thread(() =>
{
// The following loop blocks until items become available in the blocking collection.
// Then one thread is unblocked to consume that item.
foreach (var task in _tasks.GetConsumingEnumerable())
{
TryExecuteTask(task);
}
});
// Start each thread
_threads[i].IsBackground = true;
_threads[i].Start();
}
}
// This method is invoked by the runtime to schedule a task
protected override void QueueTask(Task task)
{
_tasks.Add(task);
}
// The runtime will probe if a task can be executed in the current thread.
// By returning false, we direct all tasks to be queued up.
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return false;
}
public override int MaximumConcurrencyLevel { get { return _n; } }
protected override IEnumerable<Task> GetScheduledTasks()
{
return _tasks.ToArray();
}
// Dispose is not thread-safe with other members.
// It may only be used when no more tasks will be queued
// to the scheduler. This implementation will block
// until all previously queued tasks have completed.
public void Dispose()
{
if (_threads != null)
{
_tasks.CompleteAdding();
for (int i = 0; i < _n; i++)
{
_threads[i].Join();
_threads[i] = null;
}
_threads = null;
_tasks.Dispose();
_tasks = null;
}
}
}
And the test code itself:
private void button2_Click(object sender, EventArgs e)
{
var maximum = 100;
var options = new ParallelOptions
{
MaxDegreeOfParallelism = 100,
TaskScheduler = new ThreadTaskScheduler()
};
// To prevent UI blocking
Task.Factory.StartNew(() =>
{
Parallel.For(0, maximum, options, i =>
{
var data = new Data();
// Fill data
var test = new Test(data, _url); //_url is pre-defined
var ret = test.Execute();
// Check return and display on screen
var now = DateTime.Now.ToString("HH:mm:ss");
var newText = $"{Environment.NewLine}[{now}] - {ret.ReturnId}) {ret.ReturnDescription}";
AppendTextBox(newText, ref resultTextBox);
}
}
public void AppendTextBox(string value, ref TextBox textBox)
{
if (InvokeRequired)
{
this.Invoke(new ActionRef<string, TextBox>(AppendTextBox), value, textBox);
return;
}
textBox.Text += value;
}
And the result that I get is basically this:
[10:08:56] - (0) OK
[10:08:56] - (0) OK
[10:09:23] - (0) OK
[10:09:23] - (0) OK
[10:09:49] - (0) OK
[10:09:50] - (0) OK
[10:10:15] - (0) OK
[10:10:16] - (0) OK
etc
As far as I know there's no limitation on the server side. I'm relatively new to the Parallel/Multitasking world. Is there any other way to do this? Am I missing something?
(I simplified all the code for clearness and I believe that the provided code is enough to picture the mentioned scenarios. I also didn't post the application code, but it's a simple WinForms screen just to call and show results. If any code is somehow relevant, please let me know, I can edit and post it too.)
Thanks in advance!
EDIT1: I checked on the server logs that it's receiving the requests two by two, so it's indeed something related to sending them, not receiving.
Could it be a network problem/limitation related to how the framework manages the requests/connections? Or something with the network at all (unrelated to .net)?
EDIT2: Forgot to mention, it's a SOAP webservice.
EDIT3: One of the properties that I send (inside data) needs to change for each request.
EDIT4: I noticed that there's always an interval of ~25 secs between each pair of request, if it's relevant.
I would recommend not to reinvent the wheel and just use one of the existing solutions:
Most obvious choice: if your Visual Studio license allows you can use MS Load Testing Framework, most likely you won't even have to write a single line of code: How to: Create a Web Service Test
SoapUI is a free and open source web services testing tool, it has some limited load testing capabilities
If for some reasons SoapUI is not suitable (i.e. you need to run load tests in clustered mode from several hosts or you need more enhanced reporting) you can use Apache JMeter - free and open source multiprotocol load testing tool which supports web services load testing as well.
A good solution to create load tests without write a own project is use this service https://loader.io/targets
It is free for small tests, you can POST Parameters, Header,... and you have a nice reporting.
Isnt the "two requests at a time" the result of the default maxconnection=2 limit on connectionManagement?
<configuration>
<system.net>
<connectionManagement>
<add address = "http://www.contoso.com" maxconnection = "4" />
<add address = "*" maxconnection = "2" />
</connectionManagement>
</system.net>
</configuration>
My favorite load testing library is NBomber. It has an easy and powerful API, realistic user simulations, and provides you with nice HTML reports about latency and requests per second.
I used it to test my API and wrote an article about how I did it.
I lookup relative data find that Windows store app only support async WCF calling to ensure the responsive UI. Here is a relative question.
I achieve my data service and do like that. Here is the code:
MyDataServiceContext ctx = new MyDataServiceContext(uri);
DataServiceQuery<COURSE_OK> query =
(DataServiceQuery<COURSE_OK>)(from crs in ctx.COURSE_OK
select crs);
TaskFactory<IEnumerable<COURSE_OK>> tf = new TaskFactory<IEnumerable<COURSE_OK>>();
var result = await tf.FromAsync(query.BeginExecute(null, null),
ira => query.EndExecute(ira)); // InvalidOperationException
foreach (var a in result)
{
System.Diagnostics.Debug.WriteLine("{0}", a.TITLE);
}
I succeeded only once, after that it always crash in query.EndExecute(ira) method and said InvalidOperationException was unhandled by user code.
In addition, it works well in Console Application. I guess that the main problem is Windows store app, but how to solve this?
Your function looks quite good. This is what works for me:
var queryTask = Task.Factory.FromAsync<IEnumerable<TResult>>(query.BeginExecute(null, null), (asResult) =>
{
var result = query.EndExecute(asResult).ToList();
return result;
});
Maybe you should not initialize your context on every call. Just initialize it once and reuse it every time you need it.
I have a Windows Phone 7 application that is using Silverlight with C#. This application has a method that fires off multiple web service requests. At another point in my code, I have some code that looks like the following:
myProgressBar.Visibility = Visibility.Visible;
while (AreWebServiceCallsDone() == false)
{
// Need "waiting" code here
}
// Proceed
How do I make my UI "wait" a small amount of time, without locking up the UI, and then check again to see if my web service calls are done?
Thank you!
The answer is to not make the UI wait at all but to "go with the (asynchronous) flow", as it were.
Ultimately, the async stuff in C# 5 will solve this particular problem, but there's no timeline for it's release for the desktop CLR let alone Silverlight or WP7.
I'd personally recommend looking into Microsoft.Phone.Reactive, which is the WP7 version of the Reactive Extensions (Rx) and ships with the SDK. It's a pretty big subject that takes a fair amount of time to get your head around, but can really simplify how you deal with asynchronous scenarios.
Assuming each of your web services return different types of data, I would:
Wrap each web service call in an IObservable1
Use Do to "peek" at the message and perform your side effects (like assigning the value locally)
Use Select to "normalize" the types so that they are all of the same type (required for the next step)
Use ForkJoin to execute each of the requests in parallel and to handle when each has completed
1 Creating an IObservable for your request really depends on how asynchronous pattern you are using. Assuming you're using WebClient, here's an extension method that creates an Observable from DownloadStringAsync as a sample (it may look complex but it's just handling errors and cancellation):
public static class ObservableWebClient
{
public static IObservable<string> DownloadStringObservable(
this WebClient webClient, Uri uri)
{
return Observable.Create(observer =>
{
var disposable = new CompositeDisposable();
var completedObservable = Observable.FromEvent<
DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs
>(
h => new DownloadStringCompletedEventHandler(h),
h => webClient.DownloadStringCompleted += h,
h => webClient.DownloadStringCompleted h= h
);
disposable.Add(completedObservable
.SelectMany(ev =>
{
return (ev.EventArgs.Error != null)
? Observable.Throw<string>(ev.EventArgs.Error)
: Observable.Return(ev.EventArgs.Result);
})
.Subscribe(observer));
disposable.Add(Disposable.Create(
() => webClient.CancelAsync()));
return disposable;
});
}
}
You can then use it like so:
Note that I've skipped the Do + "normalizing" steps because my data types are all the same (String). As such, I can subscribe to them all as an array (it's a subtlety of how ForkJoin works, if you were wondering)
var webClientA = new WebClient();
var webClientB = new WebClient();
var webClientC = new WebClient();
Observable.ForkJoin(
webClientA.DownloadStringObservable(uriA),
webClientB.DownloadStringObservable(uriB),
webClientC.DownloadStringObservable(uriC),
)
.ObserveOnDispatcher()
.Subscribe(dataArray =>
{
// All three have completed
this.DataA = dataArray[0];
this.DataB = dataArray[1];
this.DataC = dataArray[2];
});
You should be using an async call back method and handle the progress bar's visibility on the call back event.
By using a while, you are making the UI wait for the thread to be executed.
I used this method in my blog post here: http://www.infopoint.com/News-Events/EntryId/29/Building-a-WP7-RSS-reader-Part-1-Basics.aspx
I'm calling a SSIS package using LoadPackage(...).
Is it possible to make this call an Asynchronous call?
Yes, use an asynchronous delegate, as demostrated here:
http://msdn.microsoft.com/en-us/library/h80ttd5f.aspx
If you just want it to run in the background then yes, you can either spool up a thread or call some T-SQL to dynamically create a job (and remove it again afterwards). If you want to run it asynchronously and want a callback when it's done, then I think you're out of luck unfortunately.
Are you asking if it's 1) legal to call LoadPackage on a background thread or 2) is it possible. For #1 I can't give a definitive answer because I don't use the SSIS framework.
However #2 (as long as #1 is true) is definately doable. IMHO, you're better off using an existing framework which has API's designed to calling API's async and waiting for the results. For instance with Parellel Extensions June 08 CTP, the following code will do.
using System.Threading.Tasks;
...
var future = Future.Create(()=>LoadPackage); // Starts loading the package
// Do other stuff
var package = future.Value; // Wait for package load to complete and get the value
I'm calling an SSIS package from my UI (WPF) via an async WCF service call. Service code is:
public string ImportMarriageXML(bool isWakeUp, bool clearExistingMarriage)
{
try
{
var dts = new Microsoft.SqlServer.Dts.Runtime.Application();
using (var package = dts.LoadFromSqlServer(
ServiceSettings.Settings.SSIS.ImportMarriages,
ServiceSettings.Settings.SSIS.ServerIP,
ServiceSettings.Settings.SSIS.UserID,
ServiceSettings.Settings.SSIS.Password,
null))
{
package.InteractiveMode = false;
package.Connections["DB.STAGING"].ConnectionString = String.Format("{0};Provider={1};", DBSettings.ConnectionString(Core.Database.Staging), ServiceSettings.Settings.SSIS.Provider);
var variables = package.Variables;
variables["IsWakeUp"].Value = isWakeUp;
variables["ClearExistingMarriage"].Value = clearExistingMarriage;
variables["XmlDirectory"].Value = ServiceSettings.Settings.SSIS.Properties.XmlDirectory;
if (package.Execute() == DTSExecResult.Failure)
{
// HACK: Need to refactor this at some point. Will do for now.
var errors = new System.Text.StringBuilder();
foreach (var error in package.Errors)
errors.AppendFormat("SubComponent: {0}; Description: {1}{2}", error.SubComponent, error.Description, Environment.NewLine);
throw new ApplicationException(errors.ToString());
}
return package.Connections["Text Logging"].ConnectionString;
}
}
}
And (part of) the client-side code is as follows:
private void InvokeLoadMarriages()
{
integrationServicesServiceClient.BeginImportMarriageXML(false, OnEndImportMarriageXML, null);
}
private void OnEndImportMarriageXML(IAsyncResult asyncResult)
{
view.InvokeDisplayResults(integrationServicesServiceClient.EndImportMarriageXML(asyncResult));
}
Where BeginImportMarriageXML & EndImportMarriageXML are the generated async operations in the proxy class.