3

我正在尝试生成和调度(同时让我的 UI 线程使用progressRing.IsActive = true;),三个List对象放在 a 上BackgroundWorker,然后将所述列表传输到UI Thread,但我遇到了问题......

必须在与 DependencyObject 相同的线程上创建 DependencySource。

资源,我读过

BackgroundLogin()分班法MainWindow

    private void BackgroundLogin()
    {
        //process the form on UI Thread
        this.LoginForm(FadeOut);
        this.LoadingRing(FadeIn);

        //Start a new Thread
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        //initialize custom class WorkerThread object to store/process a result
        WorkerThread wt = new WorkerThread(this, txtEmailAddress.Text, txtPassword.Password);
        //start the worker and send the object across.
        worker.RunWorkerAsync(wt);
    }

worker_DoWork分班法MainWindow

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //grab the object
        WorkerThread wt = (WorkerThread)e.Argument;
        //check if we can login
        if (!wt.Login())
        {
            //cancel the thread
            e.Cancel = true;
        }
        else
        {
            //load additional data
            wt.UpdateAuthLbl(".. Loading New Data ..");
            wt.LoadLists();
            wt.UpdateAuthLbl(".. Data Loaded ..");
        }
        //pass the object back
        e.Result = wt;
    }

loadLists()上课方式WorkerThread

    /// <summary>
    /// Load data into the list
    /// </summary>
    public void LoadLists()
    {
        this.gene_fact_list = db.loadGeneFactTable();
        this.gene_trait_fact_list = db.loadGeneTraitFactTable(this.gene_fact_list);
        this.category_trait_list = db.loadCategoryTraits();
    }

worker_RunWorkerCompleted部分类方法,类MainWindow对象glGeneList

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //grab the finished object
        WorkerThread wt = (WorkerThread) e.Result;
        //work out if we are logged in
        Boolean LoginFlag = !e.Cancelled && e.Error == null;
        if (LoginFlag)
        {
            lblAuthentication.Content = ".. Loading Interface ..";
            //pass the finished object into memory
            this.gl = wt;
            //reset the listbox
            this.resetListBox();
        }
        this.LoginForm(LoginFlag);
    }

方法resetListBox()ListBoxItems

    /// <summary>
    /// Load the data for the form
    /// </summary>
    public void resetListBox()
    {
        if (this.gl.notNullOrEmpty())
        {
            this.ListBoxItems.Clear();
            //begin compiling the mainTab
            foreach (KeyValuePair<long, GeneNotesDataModel> kvp in this.gl.gene_fact_list)
            {
                this.ListBoxItems.Add(kvp.Value);
            }
        }
    } //close function

    //declare WPF list binding
    private ObservableCollection<GeneNotesDataModel> _listBoxItems = new ObservableCollection<GeneNotesDataModel>();

    /// <summary>
    /// Control the listbox of rsid codes
    /// </summary>
    public ObservableCollection<GeneNotesDataModel> ListBoxItems
    {
        get { return _listBoxItems; }
        set { _listBoxItems = value; }
    }

XAML ListBoxlstSnpCodes

<ListBox ItemsSource="{Binding ElementName=UI, Path=ListBoxItems}" Margin="6,38,0,60" BorderThickness="2" HorizontalAlignment="Left" Width="180" Name="lstSnpCodes" SelectionChanged="lstSnpCodes_SelectionChanged" KeyUp="OnKeyUpHandler" />

该行this.ListBoxItems.Add(kvp.Value);导致Exception发生(如果我用它替换Debug.WriteLine(kvp.Value.getValueAsString());它会运行得很好)。关于为什么我得到一个 DependencySource 异常的任何想法?为什么不能ListASlave Threadto转移Main Thread

PasteBin 链接将于 2013 年 4 月到期

4

1 回答 1

1

与其尝试直接跨线程访问属性,不如尝试访问其背后的变量。

在示例应用程序中:

private static List<object> _lst;


    static void Main(string[] args)
    {
        Task tsk =  new Task(() => _lst = new List<object>()); //task will create new thread if available and execute the Action.
        tsk.Start(); //initiates task, which initiates new List<object> on new thread.
        tsk.Wait(); //waits for task to complete.  Note that this locks main thread.
        _lst.Add(1); //Attempt to access _lst from main thread.
    }

具体到你的例子。

private ReadOnly object _lockMyList = new object();
private List _MyList;

public void SetMyList(List lst) //Use this to set list from other thread.
{
    Lock(_lockMyList)
    {
        _MyList = lst;
    }
    //Invoke Property Changed event if needed for binding.
}

public List MyList
{
    get
    {
        List lst = null;
        Lock(_lockMyList)
        {
            lst = _MyList; //You might need to do _MyList.ToList() for true thread safety
        }
        return lst;
    }
    //Property setter if needed, but use accessor method instead for setting property from other thread
}

此外,您可能需要查看 SynchronizedCollection 以查看它是否更适合您的需求。

我希望这有帮助。

于 2013-03-04T06:25:15.697 回答