S
Steve B.
Hi,
I'm building a device application that works on two threads (using VS 2005
and CF 2.0).
I'm using threads because one of my operations is quite long (up to 30
minutes or more), and I want to display the user a progress bar and messages
in a listbox.
This operation is a Sql Mobile Merge replication, but I suppose handling
exceptions in other theads is quite standard.
I've a class that handle the replication, and below is a part of the code I
use.
I'd like to know how to correctly handle any exception in the second thread
?
The "DoSynchronize" method must exit only when the replication has finished.
I use BeginSynchronize to enable firing events. If an exception occurs while
replicating, I want the exception to be thrown to the DoSynchronize calling
method.
What have I to do ?
Below is the partial code of my replication manager [1] and the form that
should display the progression (in a list box)[2]
Thanks,
Steve
[1]
public class SqlCeReplicationManager
{
private static System.Threading.AutoResetEvent _isSync = new
System.Threading.AutoResetEvent(false);
#region Synchronization progression monitoring
/// <summary>
/// Notify when a table is downloaded
/// </summary>
public event EventHandler<TableTransferedEventArgs> TableDownloaded;
/// <summary>
/// Notify when a table is uploaded
/// </summary>
public event EventHandler<TableTransferedEventArgs> TableUploaded;
/// <summary>
/// Notify the progression of the synchronization
/// </summary>
public event EventHandler<SynchronizationStepEventArgs> SynchronizationStep;
/// <summary>
/// Notify when the synchronization complete
/// </summary>
public event EventHandler<SynchronizationCompletedEventArgs>
SynchronizationCompleted;
#endregion
private void DoSynchronize(SqlCeReplication repl)
{
//repl.Synchronize();
repl.BeginSynchronize(
new AsyncCallback(this.SyncCompletedCallBack),
new OnStartTableUpload(this.OnStartTableUploadCallBack),
new OnStartTableDownload(this.OnStartTableDownloadCallBack),
new OnSynchronization(this.OnSynchronizationCallBack),
repl
);
_isSync.WaitOne();
}
private void SyncCompletedCallBack(IAsyncResult ar)
{
((SqlCeReplication)ar.AsyncState).EndSynchronize(ar);
if (this.SynchronizationCompleted != null)
{
this.SynchronizationCompleted(
this,
new SynchronizationCompletedEventArgs(new
ChangesStats((SqlCeReplication)ar.AsyncState))
);
}
_isSync.Set();
}
private void OnStartTableUploadCallBack(
IAsyncResult ar,
string tableName
)
{
if (this.TableUploaded != null)
{
this.TableUploaded(
this,
new TableTransferedEventArgs(tableName)
);
}
}
private void OnStartTableDownloadCallBack(
IAsyncResult ar,
string tableName
)
{
if (this.TableDownloaded != null)
{
this.TableDownloaded(
this,
new TableTransferedEventArgs(tableName)
);
}
}
private void OnSynchronizationCallBack(
IAsyncResult ar,
int percentComplete
)
{
if (this.SynchronizationStep != null)
{
this.SynchronizationStep(
this,
new SynchronizationStepEventArgs(percentComplete)
);
}
}
private void CancelSynchronize()
{
GetReplicationObject().CancelSynchronize();
_isSync.Set();
}
}
public partial class frmSqlRepl : Form
{
public frmSqlRepl()
{
InitializeComponent();
SqlCeReplicationManager1.TableUploaded +=
new EventHandler<TableTransferedEventArgs>(
SqlCeReplicationManager1_TableUploaded
);
SqlCeReplicationManager1.TableDownloaded +=
new EventHandler<TableTransferedEventArgs>(
SqlCeReplicationManager1_TableDownloaded
);
SqlCeReplicationManager1.SynchronizationStep +=
new EventHandler<SynchronizationStepEventArgs>(
SqlCeReplicationManager1_SynchronizationStep
);
SqlCeReplicationManager1.SynchronizationCompleted +=
new EventHandler<SynchronizationCompletedEventArgs>(
SqlCeReplicationManager1_SynchronizationComplete
);
}
delegate void AddDelegate(string msg);
void Add(string msg) // Insert a msg at the top of the listbox
{
lstOutput.Items.Insert(0, msg);
}
void SqlCeReplicationManager1_SynchronizationComplete(
object sender,
SynchronizationCompletedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"SynchronizarionComplete : " + e.Stats.ToString()
);
}
void SqlCeReplicationManager1_SynchronizationStep(
object sender,
SynchronizationStepEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"SynchronizarionStep : " + e.PercentComplete.ToString() +
"%"
);
}
void SqlCeReplicationManager1_TableDownloaded(
object sender,
TableTransferedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"TableDownloaded : " + e.TableName
);
}
void SqlCeReplicationManager1_TableUploaded(
object sender,
TableTransferedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"TableUploaded : " + e.TableName
);
}
}
I'm building a device application that works on two threads (using VS 2005
and CF 2.0).
I'm using threads because one of my operations is quite long (up to 30
minutes or more), and I want to display the user a progress bar and messages
in a listbox.
This operation is a Sql Mobile Merge replication, but I suppose handling
exceptions in other theads is quite standard.
I've a class that handle the replication, and below is a part of the code I
use.
I'd like to know how to correctly handle any exception in the second thread
?
The "DoSynchronize" method must exit only when the replication has finished.
I use BeginSynchronize to enable firing events. If an exception occurs while
replicating, I want the exception to be thrown to the DoSynchronize calling
method.
What have I to do ?
Below is the partial code of my replication manager [1] and the form that
should display the progression (in a list box)[2]
Thanks,
Steve
[1]
public class SqlCeReplicationManager
{
private static System.Threading.AutoResetEvent _isSync = new
System.Threading.AutoResetEvent(false);
#region Synchronization progression monitoring
/// <summary>
/// Notify when a table is downloaded
/// </summary>
public event EventHandler<TableTransferedEventArgs> TableDownloaded;
/// <summary>
/// Notify when a table is uploaded
/// </summary>
public event EventHandler<TableTransferedEventArgs> TableUploaded;
/// <summary>
/// Notify the progression of the synchronization
/// </summary>
public event EventHandler<SynchronizationStepEventArgs> SynchronizationStep;
/// <summary>
/// Notify when the synchronization complete
/// </summary>
public event EventHandler<SynchronizationCompletedEventArgs>
SynchronizationCompleted;
#endregion
private void DoSynchronize(SqlCeReplication repl)
{
//repl.Synchronize();
repl.BeginSynchronize(
new AsyncCallback(this.SyncCompletedCallBack),
new OnStartTableUpload(this.OnStartTableUploadCallBack),
new OnStartTableDownload(this.OnStartTableDownloadCallBack),
new OnSynchronization(this.OnSynchronizationCallBack),
repl
);
_isSync.WaitOne();
}
private void SyncCompletedCallBack(IAsyncResult ar)
{
((SqlCeReplication)ar.AsyncState).EndSynchronize(ar);
if (this.SynchronizationCompleted != null)
{
this.SynchronizationCompleted(
this,
new SynchronizationCompletedEventArgs(new
ChangesStats((SqlCeReplication)ar.AsyncState))
);
}
_isSync.Set();
}
private void OnStartTableUploadCallBack(
IAsyncResult ar,
string tableName
)
{
if (this.TableUploaded != null)
{
this.TableUploaded(
this,
new TableTransferedEventArgs(tableName)
);
}
}
private void OnStartTableDownloadCallBack(
IAsyncResult ar,
string tableName
)
{
if (this.TableDownloaded != null)
{
this.TableDownloaded(
this,
new TableTransferedEventArgs(tableName)
);
}
}
private void OnSynchronizationCallBack(
IAsyncResult ar,
int percentComplete
)
{
if (this.SynchronizationStep != null)
{
this.SynchronizationStep(
this,
new SynchronizationStepEventArgs(percentComplete)
);
}
}
private void CancelSynchronize()
{
GetReplicationObject().CancelSynchronize();
_isSync.Set();
}
}
public partial class frmSqlRepl : Form
{
public frmSqlRepl()
{
InitializeComponent();
SqlCeReplicationManager1.TableUploaded +=
new EventHandler<TableTransferedEventArgs>(
SqlCeReplicationManager1_TableUploaded
);
SqlCeReplicationManager1.TableDownloaded +=
new EventHandler<TableTransferedEventArgs>(
SqlCeReplicationManager1_TableDownloaded
);
SqlCeReplicationManager1.SynchronizationStep +=
new EventHandler<SynchronizationStepEventArgs>(
SqlCeReplicationManager1_SynchronizationStep
);
SqlCeReplicationManager1.SynchronizationCompleted +=
new EventHandler<SynchronizationCompletedEventArgs>(
SqlCeReplicationManager1_SynchronizationComplete
);
}
delegate void AddDelegate(string msg);
void Add(string msg) // Insert a msg at the top of the listbox
{
lstOutput.Items.Insert(0, msg);
}
void SqlCeReplicationManager1_SynchronizationComplete(
object sender,
SynchronizationCompletedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"SynchronizarionComplete : " + e.Stats.ToString()
);
}
void SqlCeReplicationManager1_SynchronizationStep(
object sender,
SynchronizationStepEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"SynchronizarionStep : " + e.PercentComplete.ToString() +
"%"
);
}
void SqlCeReplicationManager1_TableDownloaded(
object sender,
TableTransferedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"TableDownloaded : " + e.TableName
);
}
void SqlCeReplicationManager1_TableUploaded(
object sender,
TableTransferedEventArgs e
)
{
lstOutput.Invoke(
new AddDelegate(Add),
"TableUploaded : " + e.TableName
);
}
}