Чтобы ответить на вопрос о том, почему некоторые права доступа к ресурсам поднимают незаконную ошибку поперечного потока, а другие нет, вы можете обратиться к source code for System.Windows.Forms.Control
. Для этого требуется немного копания, но он выглядит так, как будто предлагается некоторый доступ к потокобезопасности, такой как получение свойства Text
, но установка его не является.
В действительности, обычная мудрость, позволяющая обрабатывать весь доступ к управлению, как небезопасный поток, является наилучшей практикой.
public virtual string Text {
get {
if (CacheTextInternal) {
return(text == null) ? "" : text;
}
else {
return WindowText;
}
}
set {
if (value == null) {
value = "";
}
if (value == Text) {
return;
}
if (CacheTextInternal) {
text = value;
}
WindowText = value;
OnTextChanged(EventArgs.Empty);
if(this.IsMnemonicsListenerAxSourced){
for(Control ctl = this; ctl != null; ctl = ctl.ParentInternal) {
ActiveXImpl activeXImpl = (ActiveXImpl)ctl.Properties.GetObject(PropActiveXImpl);
if(activeXImpl != null) {
activeXImpl.UpdateAccelTable();
break;
}
}
}
}
}
Обратите внимание на использование внутреннего свойства WindowText в приведенном выше коде.
/// <devdoc>
/// The current text of the Window; if the window has not yet been created, stores it in the control.
/// If the window has been created, stores the text in the underlying win32 control.
/// This property should be used whenever you want to get at the win32 control's text. For all other cases,
/// use the Text property - but note that this is overridable, and any of your code that uses it will use
/// the overridden version in controls that subclass your own.
/// </devdoc>
internal virtual string WindowText {
get {
if (!IsHandleCreated) {
if (text == null) {
return "";
}
else {
return text;
}
}
using (new MultithreadSafeCallScope()) {
// it's okay to call GetWindowText cross-thread.
//
int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(window, Handle));
// Check to see if the system supports DBCS character
// if so, double the length of the buffer.
if (SystemInformation.DbcsEnabled) {
textLen = (textLen * 2) + 1;
}
StringBuilder sb = new StringBuilder(textLen + 1);
UnsafeNativeMethods.GetWindowText(new HandleRef(window, Handle), sb, sb.Capacity);
return sb.ToString();
}
}
set {
if (value == null) value = "";
if (!WindowText.Equals(value)) {
if (IsHandleCreated) {
UnsafeNativeMethods.SetWindowText(new HandleRef(window, Handle), value);
}
else {
if (value.Length == 0) {
text = null;
}
else {
text = value;
}
}
}
}
}
Обратите внимание на использование MultithreadSafeCallScope
в get
коде. Также обратите внимание на использование свойства Handle
, которое выдает ошибку поперечного потока; Я считаю, что свойство Handle
выступает в качестве шлюза , который проверяет сквозной доступ.
public IntPtr Handle {
get {
if (checkForIllegalCrossThreadCalls &&
!inCrossThreadSafeCall &&
InvokeRequired) {
throw new InvalidOperationException(SR.GetString(SR.IllegalCrossThreadCall,
Name));
}
if (!IsHandleCreated)
{
CreateHandle();
}
return HandleInternal;
}
}
Где документировано, что 'ForeColor' является потокобезопасным? – Blorgbeard
Просто потому, что он не генерирует исключение, каждый раз не означает, что это безопасно. – Plutonix
Пожалуйста, будьте более конкретными. С какими свойствами вы обладаете уверенностью, вы можете безопасно получить доступ к перекрестным потокам? –