Clipboard.SetText(...)
very often creates considerable delay in my GUI. Set aside for now "correct-programming/design", I want to tell the user to wait a moment (line #01
), and then let him/her know if succeeded or failed (lines #06
and #10
). The thing is that I never see the "Copying..."
text (line #01
):
01| CopiedToClipboardTextBlock.Text = "Copying...";
02| try
03| {
04| // May cause considerable delay and GUI-freeze for a while...
05| Clipboard.SetText(textBlockContent);
06| CopiedToClipboardTextBlock.Text = "Copied to clipboard:\n" + textBlockContent;
07| }
08| catch (Exception e)
09| {
10| CopiedToClipboardTextBlock.Text = "Failed to copy to clipboard!";
11| }
So I thought - OK, maybe the GUI gets updated only when the event handler returns (which doesn't make sense to me...), so I tried many things, among others:
- Using
PreviewMouseDoubleClick
to doCopiedToClipboardTextBlock.Text = "Copying..."
. Didn't help... - Using new thread in which
Dispatcher.Invoke
in new thread (don't event start... I know it's quite stupid... I was desperate)
(BTW, the delay in Clipboard.SetText(...)
happens when it's about to fail. The failure is COMException: OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))
, which is almost inevitable in many cases, but that's not the main issue here...)
Update:
This is my workaround:
CopiedToClipboardTextBlock.Text = "Copying...";
Exception resultException = null;
await Task.Run(() =>
{
var t = new Thread(obj =>
{
try { Clipboard.SetText(textBlockContent); }
catch (COMException e) { resultException = e; }
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
});
if (resultException == null)
CopiedToClipboardTextBlock.Text = "Copied to clipboard:\n" + textBlockContent;
else
CopiedToClipboardTextBlock.Text = "Failed to copy to clipboard!";
The inner Thread
is due to the requirement to have STA
by Clipboard.SetText(...)
function.
I don't know, seems very verbose to me. I suspect there's a simpler solution.