Хотелось бы, чтобы звонить SetText
было бы так просто, но есть немало ошибок, с которыми вам приходится иметь дело. Вы должны убедиться, что поток, к которому вы его вызываете, работает в STA. Иногда он может завершиться с ошибкой отказа в доступе, а затем работать без проблем через несколько секунд - что-то связанное с проблемами синхронизации COM в буфере обмена. И если к вашему приложению обращаются через удаленный рабочий стол, доступ к буферу обмена оказывается поверхностным. Мы используем централизованный метод для обработки всех этих сценариев вместо прямого вызова SetText
.
@ Stecy: Вот наш централизованный код:
Класс StaHelper просто выполняет некоторый произвольный код в потоке в однопотоковой квартире (STA) - требуется для буфера обмена.
abstract class StaHelper
{
readonly ManualResetEvent _complete = new ManualResetEvent( false );
public void Go()
{
var thread = new Thread( new ThreadStart( DoWork ) )
{
IsBackground = true,
}
thread.SetApartmentState( ApartmentState.STA );
thread.Start();
}
// Thread entry method
private void DoWork()
{
try
{
_complete.Reset();
Work();
}
catch( Exception ex )
{
if( DontRetryWorkOnFailed )
throw;
else
{
try
{
Thread.Sleep( 1000 );
Work();
}
catch
{
// ex from first exception
LogAndShowMessage( ex );
}
}
}
finally
{
_complete.Set();
}
}
public bool DontRetryWorkOnFailed{ get; set; }
// Implemented in base class to do actual work.
protected abstract void Work();
}
Тогда у нас есть специальный класс для настройки текста в буфере обмена. Создание DataObject
вручную требуется в некоторых крайних случаях в некоторых версиях Windows / .NET. Я не помню точных сценариев сейчас, и это может не потребоваться в .NET 3.5.
class SetClipboardHelper : StaHelper
{
readonly string _format;
readonly object _data;
public SetClipboardHelper( string format, object data )
{
_format = format;
_data = data;
}
protected override void Work()
{
var obj = new System.Windows.Forms.DataObject(
_format,
_data
);
Clipboard.SetDataObject( obj, true );
}
}
Использование выглядит так:
new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();